Browse Source

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

Raanan Weber 7 years ago
parent
commit
9cbd3b5ee0
100 changed files with 42184 additions and 34527 deletions
  1. 8168 6144
      Playground/babylon.d.txt
  2. 0 23
      Playground/css/index.css
  3. 0 12
      Playground/debug.html
  4. 0 12
      Playground/index-local.html
  5. 0 12
      Playground/index.html
  6. 0 12
      Playground/indexStable.html
  7. 1 8
      Playground/js/index.js
  8. 0 3
      Playground/test.html
  9. BIN
      Playground/textures/amiga.jpg
  10. 7 2
      Tools/Gulp/config.json
  11. 1 13
      Tools/Gulp/gulp-validateTypedoc.js
  12. 4 1
      Tools/Gulp/gulpfile.js
  13. 2 2
      dist/babylon.glTF2Interface.d.ts
  14. 6897 6249
      dist/preview release/babylon.d.ts
  15. 35 35
      dist/preview release/babylon.js
  16. 1301 612
      dist/preview release/babylon.max.js
  17. 1301 612
      dist/preview release/babylon.no-module.max.js
  18. 36 36
      dist/preview release/babylon.worker.js
  19. 1301 612
      dist/preview release/es6.js
  20. 605 2
      dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts
  21. 61 3
      dist/preview release/gui/babylon.gui.d.ts
  22. 317 5
      dist/preview release/gui/babylon.gui.js
  23. 4 4
      dist/preview release/gui/babylon.gui.min.js
  24. 61 3
      dist/preview release/gui/babylon.gui.module.d.ts
  25. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js
  26. 118 97
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  27. 84 58
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  28. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  29. 303 339
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  30. 319 237
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  31. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  32. 304 339
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  33. 322 239
      dist/preview release/loaders/babylon.glTFFileLoader.js
  34. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  35. 304 339
      dist/preview release/loaders/babylonjs.loaders.d.ts
  36. 322 239
      dist/preview release/loaders/babylonjs.loaders.js
  37. 4 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  38. 304 339
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  39. 505 263
      dist/preview release/serializers/babylon.glTF2Serializer.d.ts
  40. 1308 555
      dist/preview release/serializers/babylon.glTF2Serializer.js
  41. 2 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  42. 505 263
      dist/preview release/serializers/babylonjs.serializers.d.ts
  43. 1308 555
      dist/preview release/serializers/babylonjs.serializers.js
  44. 2 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  45. 505 263
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  46. 10972 13738
      dist/preview release/typedocValidationBaseline.json
  47. 38 38
      dist/preview release/viewer/babylon.viewer.js
  48. 1552 849
      dist/preview release/viewer/babylon.viewer.max.js
  49. 4 1
      dist/preview release/what's new.md
  50. 2 2
      gui/src/controls/control.ts
  51. 219 0
      gui/src/controls/multiLine.ts
  52. 1 1
      gui/src/controls/textBlock.ts
  53. 132 0
      gui/src/multiLinePoint.ts
  54. 3 2
      loaders/src/glTF/1.0/babylon.glTFLoader.ts
  55. 5 5
      loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts
  56. 5 4
      loaders/src/glTF/2.0/Extensions/KHR_lights.ts
  57. 5 4
      loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts
  58. 5 4
      loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts
  59. 7 6
      loaders/src/glTF/2.0/Extensions/MSFT_lod.ts
  60. 298 236
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  61. 15 9
      loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts
  62. 59 100
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  63. 7 6
      loaders/src/glTF/2.0/babylon.glTFLoaderUtilities.ts
  64. 158 99
      loaders/src/glTF/babylon.glTFFileLoader.ts
  65. 1 6
      sandbox/index.js
  66. 710 0
      serializers/src/glTF/2.0/babylon.glTFAnimation.ts
  67. 8 8
      serializers/src/glTF/2.0/babylon.glTFData.ts
  68. 402 390
      serializers/src/glTF/2.0/babylon.glTFExporter.ts
  69. 234 212
      serializers/src/glTF/2.0/babylon.glTFMaterial.ts
  70. 23 18
      serializers/src/glTF/2.0/babylon.glTFSerializer.ts
  71. 135 0
      serializers/src/glTF/2.0/babylon.glTFUtilities.ts
  72. 12 10
      src/Actions/babylon.action.ts
  73. 149 24
      src/Actions/babylon.actionManager.ts
  74. 17 17
      src/Actions/babylon.condition.ts
  75. 5 6
      src/Animations/babylon.animation.ts
  76. 7 2
      src/Animations/babylon.runtimeAnimation.ts
  77. 63 1
      src/Audio/babylon.analyser.ts
  78. 4 4
      src/Bones/babylon.bone.ts
  79. 4 4
      src/Bones/babylon.skeleton.ts
  80. 8 14
      src/Cameras/Inputs/babylon.freeCameraMouseInput.ts
  81. 9 13
      src/Cameras/babylon.arcRotateCamera.ts
  82. 10 26
      src/Cameras/babylon.camera.ts
  83. 2 2
      src/Cameras/babylon.freeCamera.ts
  84. 123 0
      src/Cameras/babylon.stereoscopicCameras.ts
  85. 24 8
      src/Cameras/babylon.targetCamera.ts
  86. 54 46
      src/Engine/babylon.engine.ts
  87. 1 1
      src/Gamepad/Controllers/babylon.poseEnabledController.ts
  88. 1 1
      src/Gamepad/Controllers/babylon.windowsMotionController.ts
  89. 3 0
      src/Instrumentation/babylon.timeToken.ts
  90. 1 1
      src/Layer/babylon.effectLayer.ts
  91. 1 1
      src/Lights/babylon.hemisphericLight.ts
  92. 6 6
      src/Lights/babylon.light.ts
  93. 1 1
      src/Lights/babylon.shadowLight.ts
  94. 1 1
      src/Materials/Background/babylon.backgroundMaterial.ts
  95. 1 1
      src/Materials/PBR/babylon.pbrBaseMaterial.ts
  96. 5 1
      src/Materials/Textures/babylon.cubeTexture.ts
  97. 2 2
      src/Materials/Textures/babylon.dynamicTexture.ts
  98. 35 35
      src/Materials/Textures/babylon.internalTexture.ts
  99. 6 6
      src/Materials/babylon.effect.ts
  100. 0 0
      src/Materials/babylon.imageProcessingConfiguration.ts

File diff suppressed because it is too large
+ 8168 - 6144
Playground/babylon.d.txt


+ 0 - 23
Playground/css/index.css

@@ -433,29 +433,6 @@ body {
 }
 }
 
 
 /* Save form & co */
 /* Save form & co */
-
-.save-message {
-    display: none;
-    position:absolute;
-    top:40px; /* navbar top */
-    width: 100%;
-    z-index:5;
-    text-align: center;
-    font-size: 0.8em;
-    line-height: 2em;
-    cursor:pointer;
-}
-
-.save-message.light {
-    background-color: rgba(239, 239, 239, 0.9);
-    color: #7283a0;
-}
-
-.save-message.dark {
-    background-color: rgba(51, 51, 51, 0.9);
-    color: #eee;
-}
-
 .save-layer {
 .save-layer {
     display: none;
     display: none;
     position: absolute;
     position: absolute;

+ 0 - 12
Playground/debug.html

@@ -176,9 +176,6 @@
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
-        <div class="save-message" id="saveMessage">
-            This PG has missing metadata. Click save to add them.
-        </div>
     </div>
     </div>
 
 
     <div class="navbar navBar1475">
     <div class="navbar navBar1475">
@@ -273,9 +270,6 @@
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
-        <div class="save-message" id="saveMessage">
-            This PG has missing metadata. Click save to add them.
-        </div>
     </div>
     </div>
 
 
     <div class="navbar navBar1030">
     <div class="navbar navBar1030">
@@ -363,9 +357,6 @@
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
-        <div class="save-message" id="saveMessage">
-            This PG has missing metadata. Click save to add them.
-        </div>
     </div>
     </div>
 
 
     <div class="navbar navBar750">
     <div class="navbar navBar750">
@@ -450,9 +441,6 @@
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
-        <div class="save-message" id="saveMessage">
-            This PG has missing metadata. Click save to add them.
-        </div>
     </div>
     </div>
 
 
     <div class="wrapper">
     <div class="wrapper">

+ 0 - 12
Playground/index-local.html

@@ -119,9 +119,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="navbar navBar1475">
         <div class="navbar navBar1475">
@@ -215,9 +212,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="navbar navBar1030">
         <div class="navbar navBar1030">
@@ -305,9 +299,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="navbar navBar750">
         <div class="navbar navBar750">
@@ -392,9 +383,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="wrapper">
         <div class="wrapper">

+ 0 - 12
Playground/index.html

@@ -154,9 +154,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="navbar navBar1475">
         <div class="navbar navBar1475">
@@ -250,9 +247,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="navbar navBar1030">
         <div class="navbar navBar1030">
@@ -340,9 +334,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="navbar navBar750">
         <div class="navbar navBar750">
@@ -427,9 +418,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="wrapper">
         <div class="wrapper">

+ 0 - 12
Playground/indexStable.html

@@ -144,9 +144,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="navbar navBar1475">
         <div class="navbar navBar1475">
@@ -240,9 +237,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="navbar navBar1030">
         <div class="navbar navBar1030">
@@ -330,9 +324,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="navbar navBar750">
         <div class="navbar navBar750">
@@ -417,9 +408,6 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="save-message" id="saveMessage">
-                This PG has missing metadata. Click save to add them.
-            </div>
         </div>
         </div>
 
 
         <div class="wrapper">
         <div class="wrapper">

+ 1 - 8
Playground/js/index.js

@@ -53,8 +53,7 @@
         '.navbar .select .toDisplayBig a',
         '.navbar .select .toDisplayBig a',
         '.navbar .select .toDisplayBig ul li',
         '.navbar .select .toDisplayBig ul li',
         '.navbarBottom',
         '.navbarBottom',
-        '.navbarBottom .links .link',
-        '.save-message'];
+        '.navbarBottom .links .link'];
 
 
     var run = function () {
     var run = function () {
         var blockEditorChange = false;
         var blockEditorChange = false;
@@ -297,17 +296,14 @@
             }
             }
             document.getElementById("saveFormButtons").style.display = "block";
             document.getElementById("saveFormButtons").style.display = "block";
             document.getElementById("saveFormButtonOk").style.display = "inline-block";
             document.getElementById("saveFormButtonOk").style.display = "inline-block";
-            document.getElementById("saveMessage").style.display = "block";
         };
         };
         showNoMetadata();
         showNoMetadata();
-        document.getElementById("saveMessage").style.display = "none";
 
 
         var hideNoMetadata = function () {
         var hideNoMetadata = function () {
             document.getElementById("saveFormTitle").readOnly = true;
             document.getElementById("saveFormTitle").readOnly = true;
             document.getElementById("saveFormDescription").readOnly = true;
             document.getElementById("saveFormDescription").readOnly = true;
             document.getElementById("saveFormTags").readOnly = true;
             document.getElementById("saveFormTags").readOnly = true;
             document.getElementById("saveFormButtonOk").style.display = "none";
             document.getElementById("saveFormButtonOk").style.display = "none";
-            document.getElementById("saveMessage").style.display = "none";
             setToMultipleID("metadataButton", "display", "inline-block");
             setToMultipleID("metadataButton", "display", "inline-block");
         };
         };
 
 
@@ -864,9 +860,6 @@
         document.getElementById("saveFormButtonCancel").addEventListener("click", function () {
         document.getElementById("saveFormButtonCancel").addEventListener("click", function () {
             document.getElementById("saveLayer").style.display = "none";
             document.getElementById("saveLayer").style.display = "none";
         });
         });
-        document.getElementById("saveMessage").addEventListener("click", function () {
-            document.getElementById("saveMessage").style.display = "none";
-        });
         document.getElementById("mainTitle").innerHTML = "v" + BABYLON.Engine.Version;
         document.getElementById("mainTitle").innerHTML = "v" + BABYLON.Engine.Version;
 
 
         var previousHash = "";
         var previousHash = "";

+ 0 - 3
Playground/test.html

@@ -50,7 +50,4 @@
         </a>
         </a>
         <ul class="dropdown-menu" id="scriptsList"></ul>
         <ul class="dropdown-menu" id="scriptsList"></ul>
     </div>
     </div>
-</div>
-<div class="save-message" id="saveMessage">
-    This PG has missing metadata. Click save to add them.
 </div>
 </div>

BIN
Playground/textures/amiga.jpg


+ 7 - 2
Tools/Gulp/config.json

@@ -13,6 +13,7 @@
             "../../dist/preview release/babylon.d.ts",
             "../../dist/preview release/babylon.d.ts",
             "../../dist/preview release/gui/babylon.gui.d.ts",
             "../../dist/preview release/gui/babylon.gui.d.ts",
             "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts",
             "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts",
+            "../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts",
             "../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"
             "../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"
         ],
         ],
         "outputCustomConfigurationsDirectory": "../../dist/preview release/customConfigurations",
         "outputCustomConfigurationsDirectory": "../../dist/preview release/customConfigurations",
@@ -1592,7 +1593,9 @@
                     "../../serializers/src/glTF/2.0/babylon.glTFSerializer.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFSerializer.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFExporter.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFExporter.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFData.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFData.ts",
-                    "../../serializers/src/glTF/2.0/babylon.glTFMaterial.ts"
+                    "../../serializers/src/glTF/2.0/babylon.glTFMaterial.ts",
+                    "../../serializers/src/glTF/2.0/babylon.glTFAnimation.ts",
+                    "../../serializers/src/glTF/2.0/babylon.glTFUtilities.ts"
                 ],
                 ],
                 "output": "babylon.glTF2Serializer.js"
                 "output": "babylon.glTF2Serializer.js"
             }
             }
@@ -1622,6 +1625,7 @@
                     "../../gui/src/measure.ts",
                     "../../gui/src/measure.ts",
                     "../../gui/src/math2D.ts",
                     "../../gui/src/math2D.ts",
                     "../../gui/src/valueAndUnit.ts",
                     "../../gui/src/valueAndUnit.ts",
+                    "../../gui/src/multiLinePoint.ts",
                     "../../gui/src/controls/control.ts",
                     "../../gui/src/controls/control.ts",
                     "../../gui/src/controls/container.ts",
                     "../../gui/src/controls/container.ts",
                     "../../gui/src/controls/stackPanel.ts",
                     "../../gui/src/controls/stackPanel.ts",
@@ -1636,7 +1640,8 @@
                     "../../gui/src/controls/button.ts",
                     "../../gui/src/controls/button.ts",
                     "../../gui/src/controls/colorpicker.ts",
                     "../../gui/src/controls/colorpicker.ts",
                     "../../gui/src/controls/inputText.ts",
                     "../../gui/src/controls/inputText.ts",
-                    "../../gui/src/controls/virtualKeyboard.ts"
+                    "../../gui/src/controls/virtualKeyboard.ts",
+                    "../../gui/src/controls/multiLine.ts"
                 ],
                 ],
                 "output": "babylon.gui.js",
                 "output": "babylon.gui.js",
                 "buildAsModule": true,
                 "buildAsModule": true,

+ 1 - 13
Tools/Gulp/gulp-validateTypedoc.js

@@ -274,9 +274,6 @@ Validate.prototype.validateTypedocNamespaces = function (namespaces) {
     for (var a in namespace.children) {
     for (var a in namespace.children) {
         containerNode = namespace.children[a];
         containerNode = namespace.children[a];
 
 
-        // If comment contains @ignore then skip validation completely
-        if (Validate.hasTag(containerNode, 'ignore')) continue;
-
         // Account for undefined access modifiers.
         // Account for undefined access modifiers.
         if (!containerNode.flags.isPublic &&
         if (!containerNode.flags.isPublic &&
             !containerNode.flags.isPrivate &&
             !containerNode.flags.isPrivate &&
@@ -298,12 +295,10 @@ Validate.prototype.validateTypedocNamespaces = function (namespaces) {
                 "Missing text for " + containerNode.kindString + " : " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(containerNode));
                 "Missing text for " + containerNode.kindString + " : " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(containerNode));
         }
         }
 
 
-        //if comment contains tag @ignoreChildren, then don't validate children
-        var validateChildren = !Validate.hasTag(containerNode, 'ignoreChildren');
         children = containerNode.children;
         children = containerNode.children;
 
 
         //Validate Properties
         //Validate Properties
-        if (validateChildren && children) {
+        if (children) {
             for (var b in children) {
             for (var b in children) {
                 childNode = children[b];
                 childNode = children[b];
 
 
@@ -318,9 +313,6 @@ Validate.prototype.validateTypedocNamespaces = function (namespaces) {
                 // Validate Naming.
                 // Validate Naming.
                 this.validateNaming(containerNode, childNode);
                 this.validateNaming(containerNode, childNode);
 
 
-                //if comment contains @ignore then skip validation completely
-                if (Validate.hasTag(childNode, 'ignore')) continue;
-
                 if (isPublic) {
                 if (isPublic) {
                     tags = this.validateTags(childNode);
                     tags = this.validateTags(childNode);
                     if (tags) {
                     if (tags) {
@@ -340,9 +332,6 @@ Validate.prototype.validateTypedocNamespaces = function (namespaces) {
                         for (var c in signatures) {
                         for (var c in signatures) {
                             signatureNode = signatures[c];
                             signatureNode = signatures[c];
 
 
-                            //if node contains @ignore then skip validation completely
-                            if (Validate.hasTag(signatureNode, 'ignore')) continue;
-
                             if (isPublic) {
                             if (isPublic) {
                                 if (!this.validateComment(signatureNode)) {
                                 if (!this.validateComment(signatureNode)) {
                                     this.errorCallback(containerNode.name,
                                     this.errorCallback(containerNode.name,
@@ -698,7 +687,6 @@ function gulpValidateTypedoc(validationBaselineFileName, namespaceName, validate
         }
         }
 
 
         var jsFile = new Vinyl({
         var jsFile = new Vinyl({
-            cwd: process.cwd,
             base: null,
             base: null,
             path: validationBaselineFileName,
             path: validationBaselineFileName,
             contents: buffer
             contents: buffer

+ 4 - 1
Tools/Gulp/gulpfile.js

@@ -884,7 +884,10 @@ gulp.task("modules", ["prepare-dependency-tree"], function () {
  */
  */
 gulp.task("typedoc-generate", function () {
 gulp.task("typedoc-generate", function () {
     return gulp
     return gulp
-        .src(["../../dist/preview release/babylon.d.ts", "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts", "../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"])
+        .src(["../../dist/preview release/babylon.d.ts", 
+            "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts", 
+            "../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts",
+            "../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"])
         .pipe(typedoc({
         .pipe(typedoc({
             // TypeScript options (see typescript docs)
             // TypeScript options (see typescript docs)
             mode: "modules",
             mode: "modules",

+ 2 - 2
dist/babylon.glTF2Interface.d.ts

@@ -144,9 +144,9 @@ declare module BABYLON.GLTF2 {
         znear: number;
         znear: number;
     }
     }
     interface ICameraPerspective extends IProperty {
     interface ICameraPerspective extends IProperty {
-        aspectRatio: number;
+        aspectRatio?: number;
         yfov: number;
         yfov: number;
-        zfar: number;
+        zfar?: number;
         znear: number;
         znear: number;
     }
     }
     interface ICamera extends IChildRootProperty {
     interface ICamera extends IChildRootProperty {

File diff suppressed because it is too large
+ 6897 - 6249
dist/preview release/babylon.d.ts


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


File diff suppressed because it is too large
+ 1301 - 612
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 1301 - 612
dist/preview release/babylon.no-module.max.js


File diff suppressed because it is too large
+ 36 - 36
dist/preview release/babylon.worker.js


File diff suppressed because it is too large
+ 1301 - 612
dist/preview release/es6.js


+ 605 - 2
dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts

@@ -2,251 +2,854 @@
  * @ignoreChildren
  * @ignoreChildren
  * @ignore
  * @ignore
  */
  */
+declare module "babylonjs-gltf2interface" {
+    export = BABYLON.GLTF2;
+}
+/**
+ * Moduel for glTF 2.0 Interface
+ */
 declare module BABYLON.GLTF2 {
 declare module BABYLON.GLTF2 {
+    /**
+     * The datatype of the components in the attribute
+     */
     const enum AccessorComponentType {
     const enum AccessorComponentType {
+        /**
+         * Byte
+         */
         BYTE = 5120,
         BYTE = 5120,
+        /**
+         * Unsigned Byte
+         */
         UNSIGNED_BYTE = 5121,
         UNSIGNED_BYTE = 5121,
+        /**
+         * Short
+         */
         SHORT = 5122,
         SHORT = 5122,
+        /**
+         * Unsigned Short
+         */
         UNSIGNED_SHORT = 5123,
         UNSIGNED_SHORT = 5123,
+        /**
+         * Unsigned Int
+         */
         UNSIGNED_INT = 5125,
         UNSIGNED_INT = 5125,
+        /**
+         * Float
+         */
         FLOAT = 5126,
         FLOAT = 5126,
     }
     }
+    /**
+     * Specifies if the attirbute is a scalar, vector, or matrix
+     */
     const enum AccessorType {
     const enum AccessorType {
+        /**
+         * Scalar
+         */
         SCALAR = "SCALAR",
         SCALAR = "SCALAR",
+        /**
+         * Vector2
+         */
         VEC2 = "VEC2",
         VEC2 = "VEC2",
+        /**
+         * Vector3
+         */
         VEC3 = "VEC3",
         VEC3 = "VEC3",
+        /**
+         * Vector4
+         */
         VEC4 = "VEC4",
         VEC4 = "VEC4",
+        /**
+         * Matrix2x2
+         */
         MAT2 = "MAT2",
         MAT2 = "MAT2",
+        /**
+         * Matrix3x3
+         */
         MAT3 = "MAT3",
         MAT3 = "MAT3",
+        /**
+         * Matrix4x4
+         */
         MAT4 = "MAT4",
         MAT4 = "MAT4",
     }
     }
+    /**
+     * The name of the node's TRS property to modify, or the weights of the Morph Targets it instantiates
+     */
     const enum AnimationChannelTargetPath {
     const enum AnimationChannelTargetPath {
+        /**
+         * Translation
+         */
         TRANSLATION = "translation",
         TRANSLATION = "translation",
+        /**
+         * Rotation
+         */
         ROTATION = "rotation",
         ROTATION = "rotation",
+        /**
+         * Scale
+         */
         SCALE = "scale",
         SCALE = "scale",
+        /**
+         * Weights
+         */
         WEIGHTS = "weights",
         WEIGHTS = "weights",
     }
     }
+    /**
+     * Interpolation algorithm
+     */
     const enum AnimationSamplerInterpolation {
     const enum AnimationSamplerInterpolation {
+        /**
+         * The animated values are linearly interpolated between keyframes
+         */
         LINEAR = "LINEAR",
         LINEAR = "LINEAR",
+        /**
+         * The animated values remain constant to the output of the first keyframe, until the next keyframe
+         */
         STEP = "STEP",
         STEP = "STEP",
+        /**
+         * The animation's interpolation is computed using a cubic spline with specified tangents
+         */
         CUBICSPLINE = "CUBICSPLINE",
         CUBICSPLINE = "CUBICSPLINE",
     }
     }
+    /**
+     * A camera's projection.  A node can reference a camera to apply a transform to place the camera in the scene
+     */
     const enum CameraType {
     const enum CameraType {
+        /**
+         * A perspective camera containing properties to create a perspective projection matrix
+         */
         PERSPECTIVE = "perspective",
         PERSPECTIVE = "perspective",
+        /**
+         * An orthographic camera containing properties to create an orthographic projection matrix
+         */
         ORTHOGRAPHIC = "orthographic",
         ORTHOGRAPHIC = "orthographic",
     }
     }
+    /**
+     * The mime-type of the image
+     */
     const enum ImageMimeType {
     const enum ImageMimeType {
+        /**
+         * JPEG Mime-type
+         */
         JPEG = "image/jpeg",
         JPEG = "image/jpeg",
+        /**
+         * PNG Mime-type
+         */
         PNG = "image/png",
         PNG = "image/png",
     }
     }
+    /**
+     * The alpha rendering mode of the material
+     */
     const enum MaterialAlphaMode {
     const enum MaterialAlphaMode {
+        /**
+         * The alpha value is ignored and the rendered output is fully opaque
+         */
         OPAQUE = "OPAQUE",
         OPAQUE = "OPAQUE",
+        /**
+         * The rendered output is either fully opaque or fully transparent depending on the alpha value and the specified alpha cutoff value
+         */
         MASK = "MASK",
         MASK = "MASK",
+        /**
+         * The alpha value is used to composite the source and destination areas. The rendered output is combined with the background using the normal painting operation (i.e. the Porter and Duff over operator)
+         */
         BLEND = "BLEND",
         BLEND = "BLEND",
     }
     }
+    /**
+     * The type of the primitives to render
+     */
     const enum MeshPrimitiveMode {
     const enum MeshPrimitiveMode {
+        /**
+         * Points
+         */
         POINTS = 0,
         POINTS = 0,
+        /**
+         * Lines
+         */
         LINES = 1,
         LINES = 1,
+        /**
+         * Line Loop
+         */
         LINE_LOOP = 2,
         LINE_LOOP = 2,
+        /**
+         * Line Strip
+         */
         LINE_STRIP = 3,
         LINE_STRIP = 3,
+        /**
+         * Triangles
+         */
         TRIANGLES = 4,
         TRIANGLES = 4,
+        /**
+         * Triangle Strip
+         */
         TRIANGLE_STRIP = 5,
         TRIANGLE_STRIP = 5,
+        /**
+         * Triangle Fan
+         */
         TRIANGLE_FAN = 6,
         TRIANGLE_FAN = 6,
     }
     }
+    /**
+     * Magnification filter.  Valid values correspond to WebGL enums: 9728 (NEAREST) and 9729 (LINEAR)
+     */
     const enum TextureMagFilter {
     const enum TextureMagFilter {
+        /**
+         * Nearest
+         */
         NEAREST = 9728,
         NEAREST = 9728,
+        /**
+         * Linear
+         */
         LINEAR = 9729,
         LINEAR = 9729,
     }
     }
+    /**
+     * Minification filter.  All valid values correspond to WebGL enums
+     */
     const enum TextureMinFilter {
     const enum TextureMinFilter {
+        /**
+         * Nearest
+         */
         NEAREST = 9728,
         NEAREST = 9728,
+        /**
+         * Linear
+         */
         LINEAR = 9729,
         LINEAR = 9729,
+        /**
+         * Nearest Mip-Map Nearest
+         */
         NEAREST_MIPMAP_NEAREST = 9984,
         NEAREST_MIPMAP_NEAREST = 9984,
+        /**
+         * Linear Mipmap Nearest
+         */
         LINEAR_MIPMAP_NEAREST = 9985,
         LINEAR_MIPMAP_NEAREST = 9985,
+        /**
+         * Nearest Mipmap Linear
+         */
         NEAREST_MIPMAP_LINEAR = 9986,
         NEAREST_MIPMAP_LINEAR = 9986,
+        /**
+         * Linear Mipmap Linear
+         */
         LINEAR_MIPMAP_LINEAR = 9987,
         LINEAR_MIPMAP_LINEAR = 9987,
     }
     }
+    /**
+     * S (U) wrapping mode.  All valid values correspond to WebGL enums
+     */
     const enum TextureWrapMode {
     const enum TextureWrapMode {
+        /**
+         * Clamp to Edge
+         */
         CLAMP_TO_EDGE = 33071,
         CLAMP_TO_EDGE = 33071,
+        /**
+         * Mirrored Repeat
+         */
         MIRRORED_REPEAT = 33648,
         MIRRORED_REPEAT = 33648,
+        /**
+         * Repeat
+         */
         REPEAT = 10497,
         REPEAT = 10497,
     }
     }
+    /**
+     * glTF Property
+     */
     interface IProperty {
     interface IProperty {
+        /**
+         * Dictionary object with extension-specific objects
+         */
         extensions?: {
         extensions?: {
             [key: string]: any;
             [key: string]: any;
         };
         };
+        /**
+         * Application-Specific data 
+         */
         extras?: any;
         extras?: any;
     }
     }
+    /**
+     * glTF Child of Root Property
+     */
     interface IChildRootProperty extends IProperty {
     interface IChildRootProperty extends IProperty {
+        /**
+         * The user-defined name of this object
+         */
         name?: string;
         name?: string;
     }
     }
+    /**
+     * Indices of those attributes that deviate from their initialization value
+     */
     interface IAccessorSparseIndices extends IProperty {
     interface IAccessorSparseIndices extends IProperty {
+        /**
+         * The index of the bufferView with sparse indices. Referenced bufferView can't have ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER target
+         */
         bufferView: number;
         bufferView: number;
+        /**
+         * The offset relative to the start of the bufferView in bytes. Must be aligned
+         */
         byteOffset?: number;
         byteOffset?: number;
+        /**
+         * The indices data type.  Valid values correspond to WebGL enums: 5121 (UNSIGNED_BYTE), 5123 (UNSIGNED_SHORT), 5125 (UNSIGNED_INT)
+         */
         componentType: AccessorComponentType;
         componentType: AccessorComponentType;
     }
     }
+    /**
+     * Array of size accessor.sparse.count times number of components storing the displaced accessor attributes pointed by accessor.sparse.indices
+     */
     interface IAccessorSparseValues extends IProperty {
     interface IAccessorSparseValues extends IProperty {
+        /**
+         * The index of the bufferView with sparse values. Referenced bufferView can't have ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER target
+         */
         bufferView: number;
         bufferView: number;
+        /**
+         * The offset relative to the start of the bufferView in bytes. Must be aligned
+         */
         byteOffset?: number;
         byteOffset?: number;
     }
     }
+    /**
+     * Sparse storage of attributes that deviate from their initialization value
+     */
     interface IAccessorSparse extends IProperty {
     interface IAccessorSparse extends IProperty {
+        /**
+         * The number of attributes encoded in this sparse accessor
+         */
         count: number;
         count: number;
+        /**
+         * Index array of size count that points to those accessor attributes that deviate from their initialization value. Indices must strictly increase
+         */
         indices: IAccessorSparseIndices;
         indices: IAccessorSparseIndices;
+        /**
+         * Array of size count times number of components, storing the displaced accessor attributes pointed by indices. Substituted values must have the same componentType and number of components as the base accessor
+         */
         values: IAccessorSparseValues;
         values: IAccessorSparseValues;
     }
     }
+    /**
+     * A typed view into a bufferView.  A bufferView contains raw binary data.  An accessor provides a typed view into a bufferView or a subset of a bufferView similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer
+     */
     interface IAccessor extends IChildRootProperty {
     interface IAccessor extends IChildRootProperty {
+        /**
+         * The index of the bufferview
+         */
         bufferView?: number;
         bufferView?: number;
+        /**
+         * The offset relative to the start of the bufferView in bytes
+         */
         byteOffset?: number;
         byteOffset?: number;
+        /**
+         * The datatype of components in the attribute
+         */
         componentType: AccessorComponentType;
         componentType: AccessorComponentType;
+        /**
+         * Specifies whether integer data values should be normalized
+         */
         normalized?: boolean;
         normalized?: boolean;
+        /**
+         * The number of attributes referenced by this accessor
+         */
         count: number;
         count: number;
+        /**
+         * Specifies if the attribute is a scalar, vector, or matrix
+         */
         type: AccessorType;
         type: AccessorType;
+        /**
+         * Maximum value of each component in this attribute
+         */
         max?: number[];
         max?: number[];
+        /**
+         * Minimum value of each component in this attribute
+         */
         min?: number[];
         min?: number[];
+        /**
+         * Sparse storage of attributes that deviate from their initialization value
+         */
         sparse?: IAccessorSparse;
         sparse?: IAccessorSparse;
     }
     }
+    /**
+     * Targets an animation's sampler at a node's property
+     */
     interface IAnimationChannel extends IProperty {
     interface IAnimationChannel extends IProperty {
+        /**
+         * The index of a sampler in this animation used to compute the value for the target
+         */
         sampler: number;
         sampler: number;
+        /**
+         * The index of the node and TRS property to target
+         */
         target: IAnimationChannelTarget;
         target: IAnimationChannelTarget;
     }
     }
+    /**
+     * The index of the node and TRS property that an animation channel targets
+     */
     interface IAnimationChannelTarget extends IProperty {
     interface IAnimationChannelTarget extends IProperty {
+        /**
+         * The index of the node to target
+         */
         node: number;
         node: number;
+        /**
+         * The name of the node's TRS property to modify, or the weights of the Morph Targets it instantiates
+         */
         path: AnimationChannelTargetPath;
         path: AnimationChannelTargetPath;
     }
     }
+    /**
+     * Combines input and output accessors with an interpolation algorithm to define a keyframe graph (but not its target)
+     */
     interface IAnimationSampler extends IProperty {
     interface IAnimationSampler extends IProperty {
+        /**
+         * The index of an accessor containing keyframe input values, e.g., time
+         */
         input: number;
         input: number;
+        /**
+         * Interpolation algorithm
+         */
         interpolation?: AnimationSamplerInterpolation;
         interpolation?: AnimationSamplerInterpolation;
+        /**
+         * The index of an accessor, containing keyframe output values
+         */
         output: number;
         output: number;
     }
     }
+    /**
+     * A keyframe animation
+     */
     interface IAnimation extends IChildRootProperty {
     interface IAnimation extends IChildRootProperty {
+        /**
+         * An array of channels, each of which targets an animation's sampler at a node's property
+         */
         channels: IAnimationChannel[];
         channels: IAnimationChannel[];
+        /**
+         * An array of samplers that combines input and output accessors with an interpolation algorithm to define a keyframe graph (but not its target)
+         */
         samplers: IAnimationSampler[];
         samplers: IAnimationSampler[];
     }
     }
+    /**
+     * Metadata about the glTF asset
+     */
     interface IAsset extends IChildRootProperty {
     interface IAsset extends IChildRootProperty {
+        /**
+         * A copyright message suitable for display to credit the content creator
+         */
         copyright?: string;
         copyright?: string;
+        /**
+         * Tool that generated this glTF model.  Useful for debugging
+         */
         generator?: string;
         generator?: string;
+        /**
+         * The glTF version that this asset targets
+         */
         version: string;
         version: string;
+        /**
+         * The minimum glTF version that this asset targets
+         */
         minVersion?: string;
         minVersion?: string;
     }
     }
+    /**
+     * A buffer points to binary geometry, animation, or skins
+     */
     interface IBuffer extends IChildRootProperty {
     interface IBuffer extends IChildRootProperty {
+        /**
+         * The uri of the buffer.  Relative paths are relative to the .gltf file.  Instead of referencing an external file, the uri can also be a data-uri
+         */
         uri?: string;
         uri?: string;
+        /**
+         * The length of the buffer in bytes
+         */
         byteLength: number;
         byteLength: number;
     }
     }
+    /**
+     * A view into a buffer generally representing a subset of the buffer
+     */
     interface IBufferView extends IChildRootProperty {
     interface IBufferView extends IChildRootProperty {
+        /**
+         * The index of the buffer
+         */
         buffer: number;
         buffer: number;
+        /**
+         * The offset into the buffer in bytes
+         */
         byteOffset?: number;
         byteOffset?: number;
+        /**
+         * The lenth of the bufferView in bytes
+         */
         byteLength: number;
         byteLength: number;
+        /**
+         * The stride, in bytes
+         */
         byteStride?: number;
         byteStride?: number;
     }
     }
+    /**
+     * An orthographic camera containing properties to create an orthographic projection matrix
+     */
     interface ICameraOrthographic extends IProperty {
     interface ICameraOrthographic extends IProperty {
+        /**
+         * The floating-point horizontal magnification of the view. Must not be zero
+         */
         xmag: number;
         xmag: number;
+        /**
+         * The floating-point vertical magnification of the view. Must not be zero
+         */
         ymag: number;
         ymag: number;
+        /**
+         * The floating-point distance to the far clipping plane. zfar must be greater than znear
+         */
         zfar: number;
         zfar: number;
+        /**
+         * The floating-point distance to the near clipping plane
+         */
         znear: number;
         znear: number;
     }
     }
+    /**
+     * A perspective camera containing properties to create a perspective projection matrix
+     */
     interface ICameraPerspective extends IProperty {
     interface ICameraPerspective extends IProperty {
-        aspectRatio: number;
+        /**
+         * The floating-point aspect ratio of the field of view
+         */
+        aspectRatio?: number;
+        /**
+         * The floating-point vertical field of view in radians
+         */
         yfov: number;
         yfov: number;
-        zfar: number;
+        /**
+         * The floating-point distance to the far clipping plane
+         */
+        zfar?: number;
+        /**
+         * The floating-point distance to the near clipping plane
+         */
         znear: number;
         znear: number;
     }
     }
+    /**
+     * A camera's projection.  A node can reference a camera to apply a transform to place the camera in the scene
+     */
     interface ICamera extends IChildRootProperty {
     interface ICamera extends IChildRootProperty {
+        /**
+         * An orthographic camera containing properties to create an orthographic projection matrix
+         */
         orthographic?: ICameraOrthographic;
         orthographic?: ICameraOrthographic;
+        /**
+         * A perspective camera containing properties to create a perspective projection matrix
+         */
         perspective?: ICameraPerspective;
         perspective?: ICameraPerspective;
+        /**
+         * Specifies if the camera uses a perspective or orthographic projection
+         */
         type: CameraType;
         type: CameraType;
     }
     }
+    /**
+     * Image data used to create a texture. Image can be referenced by URI or bufferView index. mimeType is required in the latter case
+     */
     interface IImage extends IChildRootProperty {
     interface IImage extends IChildRootProperty {
+        /**
+         * The uri of the image.  Relative paths are relative to the .gltf file.  Instead of referencing an external file, the uri can also be a data-uri.  The image format must be jpg or png
+         */
         uri?: string;
         uri?: string;
+        /**
+         * The image's MIME type
+         */
         mimeType?: ImageMimeType;
         mimeType?: ImageMimeType;
+        /**
+         * The index of the bufferView that contains the image. Use this instead of the image's uri property
+         */
         bufferView?: number;
         bufferView?: number;
     }
     }
+    /**
+     * Material Normal Texture Info
+     */
     interface IMaterialNormalTextureInfo extends ITextureInfo {
     interface IMaterialNormalTextureInfo extends ITextureInfo {
+        /**
+         * The scalar multiplier applied to each normal vector of the normal texture
+         */
         scale?: number;
         scale?: number;
     }
     }
+    /**
+     * Material Occlusion Texture Info
+     */
     interface IMaterialOcclusionTextureInfo extends ITextureInfo {
     interface IMaterialOcclusionTextureInfo extends ITextureInfo {
+        /**
+         * A scalar multiplier controlling the amount of occlusion applied
+         */
         strength?: number;
         strength?: number;
     }
     }
+    /**
+     * A set of parameter values that are used to define the metallic-roughness material model from Physically-Based Rendering (PBR) methodology
+     */
     interface IMaterialPbrMetallicRoughness {
     interface IMaterialPbrMetallicRoughness {
+        /**
+         * The material's base color factor
+         */
         baseColorFactor?: number[];
         baseColorFactor?: number[];
+        /**
+         * The base color texture
+         */
         baseColorTexture?: ITextureInfo;
         baseColorTexture?: ITextureInfo;
+        /**
+         * The metalness of the material
+         */
         metallicFactor?: number;
         metallicFactor?: number;
+        /**
+         * The roughness of the material
+         */
         roughnessFactor?: number;
         roughnessFactor?: number;
+        /**
+         * The metallic-roughness texture
+         */
         metallicRoughnessTexture?: ITextureInfo;
         metallicRoughnessTexture?: ITextureInfo;
     }
     }
+    /**
+     * The material appearance of a primitive
+     */
     interface IMaterial extends IChildRootProperty {
     interface IMaterial extends IChildRootProperty {
+        /**
+         * A set of parameter values that are used to define the metallic-roughness material model from Physically-Based Rendering (PBR) methodology. When not specified, all the default values of pbrMetallicRoughness apply
+         */
         pbrMetallicRoughness?: IMaterialPbrMetallicRoughness;
         pbrMetallicRoughness?: IMaterialPbrMetallicRoughness;
+        /**
+         * The normal map texture
+         */
         normalTexture?: IMaterialNormalTextureInfo;
         normalTexture?: IMaterialNormalTextureInfo;
+        /**
+         * The occlusion map texture
+         */
         occlusionTexture?: IMaterialOcclusionTextureInfo;
         occlusionTexture?: IMaterialOcclusionTextureInfo;
+        /**
+         * The emissive map texture
+         */
         emissiveTexture?: ITextureInfo;
         emissiveTexture?: ITextureInfo;
+        /**
+         * The RGB components of the emissive color of the material. These values are linear. If an emissiveTexture is specified, this value is multiplied with the texel values
+         */
         emissiveFactor?: number[];
         emissiveFactor?: number[];
+        /**
+         * The alpha rendering mode of the material
+         */
         alphaMode?: MaterialAlphaMode;
         alphaMode?: MaterialAlphaMode;
+        /**
+         * The alpha cutoff value of the material
+         */
         alphaCutoff?: number;
         alphaCutoff?: number;
+        /**
+         * Specifies whether the material is double sided
+         */
         doubleSided?: boolean;
         doubleSided?: boolean;
     }
     }
+    /**
+     * Geometry to be rendered with the given material
+     */
     interface IMeshPrimitive extends IProperty {
     interface IMeshPrimitive extends IProperty {
+        /**
+         * A dictionary object, where each key corresponds to mesh attribute semantic and each value is the index of the accessor containing attribute's data
+         */
         attributes: {
         attributes: {
             [name: string]: number;
             [name: string]: number;
         };
         };
+        /**
+         * The index of the accessor that contains the indices
+         */
         indices?: number;
         indices?: number;
+        /**
+         * The index of the material to apply to this primitive when rendering
+         */
         material?: number;
         material?: number;
+        /**
+         * The type of primitives to render. All valid values correspond to WebGL enums
+         */
         mode?: MeshPrimitiveMode;
         mode?: MeshPrimitiveMode;
+        /**
+         * An array of Morph Targets, each  Morph Target is a dictionary mapping attributes (only POSITION, NORMAL, and TANGENT supported) to their deviations in the Morph Target
+         */
         targets?: {
         targets?: {
             [name: string]: number;
             [name: string]: number;
         }[];
         }[];
     }
     }
+    /**
+     * A set of primitives to be rendered.  A node can contain one mesh.  A node's transform places the mesh in the scene
+     */
     interface IMesh extends IChildRootProperty {
     interface IMesh extends IChildRootProperty {
+        /**
+         * An array of primitives, each defining geometry to be rendered with a material
+         */
         primitives: IMeshPrimitive[];
         primitives: IMeshPrimitive[];
+        /**
+         * Array of weights to be applied to the Morph Targets
+         */
         weights?: number[];
         weights?: number[];
     }
     }
+    /**
+     * A node in the node hierarchy
+     */
     interface INode extends IChildRootProperty {
     interface INode extends IChildRootProperty {
+        /**
+         * The index of the camera referenced by this node
+         */
         camera?: number;
         camera?: number;
+        /**
+         * The indices of this node's children
+         */
         children?: number[];
         children?: number[];
+        /**
+         * The index of the skin referenced by this node
+         */
         skin?: number;
         skin?: number;
+        /**
+         * A floating-point 4x4 transformation matrix stored in column-major order
+         */
         matrix?: number[];
         matrix?: number[];
+        /**
+         * The index of the mesh in this node
+         */
         mesh?: number;
         mesh?: number;
+        /**
+         * The node's unit quaternion rotation in the order (x, y, z, w), where w is the scalar
+         */
         rotation?: number[];
         rotation?: number[];
+        /**
+         * The node's non-uniform scale, given as the scaling factors along the x, y, and z axes
+         */
         scale?: number[];
         scale?: number[];
+        /**
+         * The node's translation along the x, y, and z axes
+         */
         translation?: number[];
         translation?: number[];
+        /**
+         * The weights of the instantiated Morph Target. Number of elements must match number of Morph Targets of used mesh
+         */
         weights?: number[];
         weights?: number[];
     }
     }
+    /**
+     * Texture sampler properties for filtering and wrapping modes
+     */
     interface ISampler extends IChildRootProperty {
     interface ISampler extends IChildRootProperty {
+        /**
+         * Magnification filter.  Valid values correspond to WebGL enums: 9728 (NEAREST) and 9729 (LINEAR)
+         */
         magFilter?: TextureMagFilter;
         magFilter?: TextureMagFilter;
+        /**
+         * Minification filter.  All valid values correspond to WebGL enums
+         */
         minFilter?: TextureMinFilter;
         minFilter?: TextureMinFilter;
+        /**
+         * S (U) wrapping mode.  All valid values correspond to WebGL enums
+         */
         wrapS?: TextureWrapMode;
         wrapS?: TextureWrapMode;
+        /**
+         * T (V) wrapping mode.  All valid values correspond to WebGL enums
+         */
         wrapT?: TextureWrapMode;
         wrapT?: TextureWrapMode;
     }
     }
+    /**
+     * The root nodes of a scene
+     */
     interface IScene extends IChildRootProperty {
     interface IScene extends IChildRootProperty {
+        /**
+         * The indices of each root node
+         */
         nodes: number[];
         nodes: number[];
     }
     }
+    /**
+     * Joints and matrices defining a skin
+     */
     interface ISkin extends IChildRootProperty {
     interface ISkin extends IChildRootProperty {
+        /**
+         * The index of the accessor containing the floating-point 4x4 inverse-bind matrices.  The default is that each matrix is a 4x4 identity matrix, which implies that inverse-bind matrices were pre-applied
+         */
         inverseBindMatrices?: number;
         inverseBindMatrices?: number;
+        /**
+         * The index of the node used as a skeleton root. When undefined, joints transforms resolve to scene root
+         */
         skeleton?: number;
         skeleton?: number;
+        /**
+         * Indices of skeleton nodes, used as joints in this skin.  The array length must be the same as the count property of the inverseBindMatrices accessor (when defined)
+         */
         joints: number[];
         joints: number[];
     }
     }
+    /**
+     * A texture and its sampler
+     */
     interface ITexture extends IChildRootProperty {
     interface ITexture extends IChildRootProperty {
+        /**
+         * The index of the sampler used by this texture. When undefined, a sampler with repeat wrapping and auto filtering should be used
+         */
         sampler?: number;
         sampler?: number;
+        /**
+         * The index of the image used by this texture
+         */
         source: number;
         source: number;
     }
     }
+    /**
+     * Reference to a texture
+     */
     interface ITextureInfo {
     interface ITextureInfo {
+        /**
+         * The index of the texture
+         */
         index: number;
         index: number;
+        /**
+         * The set index of texture's TEXCOORD attribute used for texture coordinate mapping
+         */
         texCoord?: number;
         texCoord?: number;
     }
     }
+    /**
+     * The root object for a glTF asset
+     */
     interface IGLTF extends IProperty {
     interface IGLTF extends IProperty {
+        /**
+         * An array of accessors. An accessor is a typed view into a bufferView
+         */
         accessors?: IAccessor[];
         accessors?: IAccessor[];
+        /**
+         * An array of keyframe animations
+         */
         animations?: IAnimation[];
         animations?: IAnimation[];
+        /**
+         * Metadata about the glTF asset
+         */
         asset: IAsset;
         asset: IAsset;
+        /**
+         * An array of buffers.  A buffer points to binary geometry, animation, or skins
+         */
         buffers?: IBuffer[];
         buffers?: IBuffer[];
+        /**
+         * An array of bufferViews.  A bufferView is a view into a buffer generally representing a subset of the buffer
+         */
         bufferViews?: IBufferView[];
         bufferViews?: IBufferView[];
+        /**
+         * An array of cameras
+         */
         cameras?: ICamera[];
         cameras?: ICamera[];
+        /**
+         * Names of glTF extensions used somewhere in this asset
+         */
         extensionsUsed?: string[];
         extensionsUsed?: string[];
+        /**
+         * Names of glTF extensions required to properly load this asset
+         */
         extensionsRequired?: string[];
         extensionsRequired?: string[];
+        /**
+         * An array of images.  An image defines data used to create a texture
+         */
         images?: IImage[];
         images?: IImage[];
+        /**
+         * An array of materials.  A material defines the appearance of a primitive
+         */
         materials?: IMaterial[];
         materials?: IMaterial[];
+        /**
+         * An array of meshes.  A mesh is a set of primitives to be rendered
+         */
         meshes?: IMesh[];
         meshes?: IMesh[];
+        /**
+         * An array of nodes
+         */
         nodes?: INode[];
         nodes?: INode[];
+        /**
+         * An array of samplers.  A sampler contains properties for texture filtering and wrapping modes
+         */
         samplers?: ISampler[];
         samplers?: ISampler[];
+        /**
+         * The index of the default scene
+         */
         scene?: number;
         scene?: number;
+        /**
+         * An array of scenes
+         */
         scenes?: IScene[];
         scenes?: IScene[];
+        /**
+         * An array of skins.  A skin is defined by joints and matrices
+         */
         skins?: ISkin[];
         skins?: ISkin[];
+        /**
+         * An array of textures
+         */
         textures?: ITexture[];
         textures?: ITexture[];
     }
     }
 }
 }

+ 61 - 3
dist/preview release/gui/babylon.gui.d.ts

@@ -152,6 +152,28 @@ declare module BABYLON.GUI {
 
 
 
 
 declare module BABYLON.GUI {
 declare module BABYLON.GUI {
+    class MultiLinePoint {
+        private _multiLine;
+        private _x;
+        private _y;
+        private _control;
+        private _mesh;
+        private _controlObserver;
+        private _meshObserver;
+        _point: Vector2;
+        constructor(multiLine: MultiLine);
+        x: string | number;
+        y: string | number;
+        control: Nullable<Control>;
+        mesh: Nullable<AbstractMesh>;
+        translate(): Vector2;
+        private _translatePoint();
+        dispose(): void;
+    }
+}
+
+
+declare module BABYLON.GUI {
     class Control {
     class Control {
         name: string | undefined;
         name: string | undefined;
         private _alpha;
         private _alpha;
@@ -260,7 +282,7 @@ declare module BABYLON.GUI {
         readonly heightInPixels: number;
         readonly heightInPixels: number;
         fontFamily: string;
         fontFamily: string;
         fontStyle: string;
         fontStyle: string;
-        /** @ignore */
+        /** @hidden */
         readonly _isFontSizeInPercentage: boolean;
         readonly _isFontSizeInPercentage: boolean;
         readonly fontSizeInPixels: number;
         readonly fontSizeInPixels: number;
         fontSize: string | number;
         fontSize: string | number;
@@ -289,7 +311,7 @@ declare module BABYLON.GUI {
         readonly centerY: number;
         readonly centerY: number;
         constructor(name?: string | undefined);
         constructor(name?: string | undefined);
         protected _getTypeName(): string;
         protected _getTypeName(): string;
-        /** @ignore */
+        /** @hidden */
         _resetFontCache(): void;
         _resetFontCache(): void;
         getLocalCoordinates(globalCoordinates: Vector2): Vector2;
         getLocalCoordinates(globalCoordinates: Vector2): Vector2;
         getLocalCoordinatesToRef(globalCoordinates: Vector2, result: Vector2): Control;
         getLocalCoordinatesToRef(globalCoordinates: Vector2, result: Vector2): Control;
@@ -646,7 +668,7 @@ declare module BABYLON.GUI {
             name?: string | undefined, text?: string);
             name?: string | undefined, text?: string);
         protected _getTypeName(): string;
         protected _getTypeName(): string;
         private _drawText(text, textWidth, y, context);
         private _drawText(text, textWidth, y, context);
-        /** @ignore */
+        /** @hidden */
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _applyStates(context: CanvasRenderingContext2D): void;
         protected _applyStates(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -852,3 +874,39 @@ declare module BABYLON.GUI {
         static CreateDefaultLayout(): VirtualKeyboard;
         static CreateDefaultLayout(): VirtualKeyboard;
     }
     }
 }
 }
+
+
+declare module BABYLON.GUI {
+    class MultiLine extends Control {
+        name: string | undefined;
+        private _lineWidth;
+        private _dash;
+        private _points;
+        private _minX;
+        private _minY;
+        private _maxX;
+        private _maxY;
+        constructor(name?: string | undefined);
+        dash: Array<number>;
+        getAt(index: number): MultiLinePoint;
+        onPointUpdate: () => void;
+        add(...items: (AbstractMesh | Control | {
+            x: string | number;
+            y: string | number;
+        })[]): MultiLinePoint[];
+        push(item?: (AbstractMesh | Control | {
+            x: string | number;
+            y: string | number;
+        })): MultiLinePoint;
+        remove(value: number | MultiLinePoint): void;
+        lineWidth: number;
+        horizontalAlignment: number;
+        verticalAlignment: number;
+        protected _getTypeName(): string;
+        _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        _measure(): void;
+        protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        dispose(): void;
+    }
+}

+ 317 - 5
dist/preview release/gui/babylon.gui.js

@@ -871,6 +871,119 @@ var BABYLON;
 
 
 //# sourceMappingURL=valueAndUnit.js.map
 //# sourceMappingURL=valueAndUnit.js.map
 
 
+/// <reference path="../../dist/preview release/babylon.d.ts"/>
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
+        var MultiLinePoint = /** @class */ (function () {
+            function MultiLinePoint(multiLine) {
+                this._multiLine = multiLine;
+                this._x = new GUI.ValueAndUnit(0);
+                this._y = new GUI.ValueAndUnit(0);
+                this._point = new BABYLON.Vector2(0, 0);
+            }
+            Object.defineProperty(MultiLinePoint.prototype, "x", {
+                get: function () {
+                    return this._x.toString(this._multiLine._host);
+                },
+                set: function (value) {
+                    if (this._x.toString(this._multiLine._host) === value) {
+                        return;
+                    }
+                    if (this._x.fromString(value)) {
+                        this._multiLine._markAsDirty();
+                    }
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(MultiLinePoint.prototype, "y", {
+                get: function () {
+                    return this._y.toString(this._multiLine._host);
+                },
+                set: function (value) {
+                    if (this._y.toString(this._multiLine._host) === value) {
+                        return;
+                    }
+                    if (this._y.fromString(value)) {
+                        this._multiLine._markAsDirty();
+                    }
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(MultiLinePoint.prototype, "control", {
+                get: function () {
+                    return this._control;
+                },
+                set: function (value) {
+                    if (this._control === value) {
+                        return;
+                    }
+                    if (this._control && this._controlObserver) {
+                        this._control.onDirtyObservable.remove(this._controlObserver);
+                        this._controlObserver = null;
+                    }
+                    this._control = value;
+                    if (this._control) {
+                        this._controlObserver = this._control.onDirtyObservable.add(this._multiLine.onPointUpdate);
+                    }
+                    this._multiLine._markAsDirty();
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(MultiLinePoint.prototype, "mesh", {
+                get: function () {
+                    return this._mesh;
+                },
+                set: function (value) {
+                    if (this._mesh === value) {
+                        return;
+                    }
+                    if (this._mesh && this._meshObserver) {
+                        this._mesh.getScene().onAfterCameraRenderObservable.remove(this._meshObserver);
+                    }
+                    this._mesh = value;
+                    if (this._mesh) {
+                        this._meshObserver = this._mesh.getScene().onAfterCameraRenderObservable.add(this._multiLine.onPointUpdate);
+                    }
+                    this._multiLine._markAsDirty();
+                },
+                enumerable: true,
+                configurable: true
+            });
+            MultiLinePoint.prototype.translate = function () {
+                this._point = this._translatePoint();
+                return this._point;
+            };
+            MultiLinePoint.prototype._translatePoint = function () {
+                if (this._mesh != null) {
+                    return this._multiLine._host.getProjectedPosition(this._mesh.getBoundingInfo().boundingSphere.center, this._mesh.getWorldMatrix());
+                }
+                else if (this._control != null) {
+                    return new BABYLON.Vector2(this._control.centerX, this._control.centerY);
+                }
+                else {
+                    var host = this._multiLine._host;
+                    var xValue = this._x.getValueInPixel(host, Number(host._canvas.width));
+                    var yValue = this._y.getValueInPixel(host, Number(host._canvas.height));
+                    return new BABYLON.Vector2(xValue, yValue);
+                }
+            };
+            MultiLinePoint.prototype.dispose = function () {
+                this.control = null;
+                this.mesh = null;
+            };
+            return MultiLinePoint;
+        }());
+        GUI.MultiLinePoint = MultiLinePoint;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=multiLinePoint.js.map
+
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 var BABYLON;
 var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
@@ -1159,7 +1272,7 @@ var BABYLON;
                 configurable: true
                 configurable: true
             });
             });
             Object.defineProperty(Control.prototype, "_isFontSizeInPercentage", {
             Object.defineProperty(Control.prototype, "_isFontSizeInPercentage", {
-                /** @ignore */
+                /** @hidden */
                 get: function () {
                 get: function () {
                     return this._fontSize.isPercentage;
                     return this._fontSize.isPercentage;
                 },
                 },
@@ -1426,7 +1539,7 @@ var BABYLON;
             Control.prototype._getTypeName = function () {
             Control.prototype._getTypeName = function () {
                 return "Control";
                 return "Control";
             };
             };
-            /** @ignore */
+            /** @hidden */
             Control.prototype._resetFontCache = function () {
             Control.prototype._resetFontCache = function () {
                 this._fontSet = true;
                 this._fontSet = true;
             };
             };
@@ -3625,7 +3738,7 @@ var BABYLON;
                 }
                 }
                 context.fillText(text, this._currentMeasure.left + x, y);
                 context.fillText(text, this._currentMeasure.left + x, y);
             };
             };
-            /** @ignore */
+            /** @hidden */
             TextBlock.prototype._draw = function (parentMeasure, context) {
             TextBlock.prototype._draw = function (parentMeasure, context) {
                 context.save();
                 context.save();
                 this._applyStates(context);
                 this._applyStates(context);
@@ -4173,8 +4286,6 @@ var BABYLON;
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
 
 
-//# sourceMappingURL=button.js.map
-
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 
 var BABYLON;
 var BABYLON;
@@ -5137,6 +5248,207 @@ var BABYLON;
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));
 
 
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
+        var MultiLine = /** @class */ (function (_super) {
+            __extends(MultiLine, _super);
+            function MultiLine(name) {
+                var _this = _super.call(this, name) || this;
+                _this.name = name;
+                _this._lineWidth = 1;
+                _this.onPointUpdate = function () {
+                    _this._markAsDirty();
+                };
+                _this.isHitTestVisible = false;
+                _this._horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+                _this._verticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_TOP;
+                _this._dash = [];
+                _this._points = [];
+                return _this;
+            }
+            Object.defineProperty(MultiLine.prototype, "dash", {
+                get: function () {
+                    return this._dash;
+                },
+                set: function (value) {
+                    if (this._dash === value) {
+                        return;
+                    }
+                    this._dash = value;
+                    this._markAsDirty();
+                },
+                enumerable: true,
+                configurable: true
+            });
+            MultiLine.prototype.getAt = function (index) {
+                if (!this._points[index]) {
+                    this._points[index] = new GUI.MultiLinePoint(this);
+                }
+                return this._points[index];
+            };
+            MultiLine.prototype.add = function () {
+                var _this = this;
+                var items = [];
+                for (var _i = 0; _i < arguments.length; _i++) {
+                    items[_i] = arguments[_i];
+                }
+                return items.map(function (item) { return _this.push(item); });
+            };
+            MultiLine.prototype.push = function (item) {
+                var point = this.getAt(this._points.length);
+                if (item == null)
+                    return point;
+                if (item instanceof BABYLON.AbstractMesh) {
+                    point.mesh = item;
+                }
+                else if (item instanceof GUI.Control) {
+                    point.control = item;
+                }
+                else if (item.x != null && item.y != null) {
+                    point.x = item.x;
+                    point.y = item.y;
+                }
+                return point;
+            };
+            MultiLine.prototype.remove = function (value) {
+                var index;
+                if (value instanceof GUI.MultiLinePoint) {
+                    index = this._points.indexOf(value);
+                    if (index === -1) {
+                        return;
+                    }
+                }
+                else {
+                    index = value;
+                }
+                var point = this._points[index];
+                if (!point) {
+                    return;
+                }
+                point.dispose();
+                this._points.splice(index, 1);
+            };
+            Object.defineProperty(MultiLine.prototype, "lineWidth", {
+                get: function () {
+                    return this._lineWidth;
+                },
+                set: function (value) {
+                    if (this._lineWidth === value) {
+                        return;
+                    }
+                    this._lineWidth = value;
+                    this._markAsDirty();
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(MultiLine.prototype, "horizontalAlignment", {
+                set: function (value) {
+                    return;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(MultiLine.prototype, "verticalAlignment", {
+                set: function (value) {
+                    return;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            MultiLine.prototype._getTypeName = function () {
+                return "MultiLine";
+            };
+            MultiLine.prototype._draw = function (parentMeasure, context) {
+                context.save();
+                if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                    context.shadowColor = this.shadowColor;
+                    context.shadowBlur = this.shadowBlur;
+                    context.shadowOffsetX = this.shadowOffsetX;
+                    context.shadowOffsetY = this.shadowOffsetY;
+                }
+                this._applyStates(context);
+                if (this._processMeasures(parentMeasure, context)) {
+                    context.strokeStyle = this.color;
+                    context.lineWidth = this._lineWidth;
+                    context.setLineDash(this._dash);
+                    context.beginPath();
+                    var first = true; //first index is not necessarily 0
+                    this._points.forEach(function (point) {
+                        if (!point) {
+                            return;
+                        }
+                        if (first) {
+                            context.moveTo(point._point.x, point._point.y);
+                            first = false;
+                        }
+                        else {
+                            context.lineTo(point._point.x, point._point.y);
+                        }
+                    });
+                    context.stroke();
+                }
+                context.restore();
+            };
+            MultiLine.prototype._additionalProcessing = function (parentMeasure, context) {
+                var _this = this;
+                this._minX = null;
+                this._minY = null;
+                this._maxX = null;
+                this._maxY = null;
+                this._points.forEach(function (point, index) {
+                    if (!point) {
+                        return;
+                    }
+                    point.translate();
+                    if (_this._minX == null || point._point.x < _this._minX)
+                        _this._minX = point._point.x;
+                    if (_this._minY == null || point._point.y < _this._minY)
+                        _this._minY = point._point.y;
+                    if (_this._maxX == null || point._point.x > _this._maxX)
+                        _this._maxX = point._point.x;
+                    if (_this._maxY == null || point._point.y > _this._maxY)
+                        _this._maxY = point._point.y;
+                });
+                if (this._minX == null)
+                    this._minX = 0;
+                if (this._minY == null)
+                    this._minY = 0;
+                if (this._maxX == null)
+                    this._maxX = 0;
+                if (this._maxY == null)
+                    this._maxY = 0;
+            };
+            MultiLine.prototype._measure = function () {
+                if (this._minX == null || this._maxX == null || this._minY == null || this._maxY == null) {
+                    return;
+                }
+                this._currentMeasure.width = Math.abs(this._maxX - this._minX) + this._lineWidth;
+                this._currentMeasure.height = Math.abs(this._maxY - this._minY) + this._lineWidth;
+            };
+            MultiLine.prototype._computeAlignment = function (parentMeasure, context) {
+                if (this._minX == null || this._minY == null) {
+                    return;
+                }
+                this._currentMeasure.left = this._minX - this._lineWidth / 2;
+                this._currentMeasure.top = this._minY - this._lineWidth / 2;
+            };
+            MultiLine.prototype.dispose = function () {
+                while (this._points.length > 0) {
+                    this.remove(this._points.length - 1);
+                }
+                _super.prototype.dispose.call(this);
+            };
+            return MultiLine;
+        }(GUI.Control));
+        GUI.MultiLine = MultiLine;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));
+
     
     
 
 
     return BABYLON.GUI;
     return BABYLON.GUI;

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


+ 61 - 3
dist/preview release/gui/babylon.gui.module.d.ts

@@ -157,6 +157,28 @@ declare module BABYLON.GUI {
 
 
 
 
 declare module BABYLON.GUI {
 declare module BABYLON.GUI {
+    class MultiLinePoint {
+        private _multiLine;
+        private _x;
+        private _y;
+        private _control;
+        private _mesh;
+        private _controlObserver;
+        private _meshObserver;
+        _point: Vector2;
+        constructor(multiLine: MultiLine);
+        x: string | number;
+        y: string | number;
+        control: Nullable<Control>;
+        mesh: Nullable<AbstractMesh>;
+        translate(): Vector2;
+        private _translatePoint();
+        dispose(): void;
+    }
+}
+
+
+declare module BABYLON.GUI {
     class Control {
     class Control {
         name: string | undefined;
         name: string | undefined;
         private _alpha;
         private _alpha;
@@ -265,7 +287,7 @@ declare module BABYLON.GUI {
         readonly heightInPixels: number;
         readonly heightInPixels: number;
         fontFamily: string;
         fontFamily: string;
         fontStyle: string;
         fontStyle: string;
-        /** @ignore */
+        /** @hidden */
         readonly _isFontSizeInPercentage: boolean;
         readonly _isFontSizeInPercentage: boolean;
         readonly fontSizeInPixels: number;
         readonly fontSizeInPixels: number;
         fontSize: string | number;
         fontSize: string | number;
@@ -294,7 +316,7 @@ declare module BABYLON.GUI {
         readonly centerY: number;
         readonly centerY: number;
         constructor(name?: string | undefined);
         constructor(name?: string | undefined);
         protected _getTypeName(): string;
         protected _getTypeName(): string;
-        /** @ignore */
+        /** @hidden */
         _resetFontCache(): void;
         _resetFontCache(): void;
         getLocalCoordinates(globalCoordinates: Vector2): Vector2;
         getLocalCoordinates(globalCoordinates: Vector2): Vector2;
         getLocalCoordinatesToRef(globalCoordinates: Vector2, result: Vector2): Control;
         getLocalCoordinatesToRef(globalCoordinates: Vector2, result: Vector2): Control;
@@ -651,7 +673,7 @@ declare module BABYLON.GUI {
             name?: string | undefined, text?: string);
             name?: string | undefined, text?: string);
         protected _getTypeName(): string;
         protected _getTypeName(): string;
         private _drawText(text, textWidth, y, context);
         private _drawText(text, textWidth, y, context);
-        /** @ignore */
+        /** @hidden */
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _applyStates(context: CanvasRenderingContext2D): void;
         protected _applyStates(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
@@ -857,3 +879,39 @@ declare module BABYLON.GUI {
         static CreateDefaultLayout(): VirtualKeyboard;
         static CreateDefaultLayout(): VirtualKeyboard;
     }
     }
 }
 }
+
+
+declare module BABYLON.GUI {
+    class MultiLine extends Control {
+        name: string | undefined;
+        private _lineWidth;
+        private _dash;
+        private _points;
+        private _minX;
+        private _minY;
+        private _maxX;
+        private _maxY;
+        constructor(name?: string | undefined);
+        dash: Array<number>;
+        getAt(index: number): MultiLinePoint;
+        onPointUpdate: () => void;
+        add(...items: (AbstractMesh | Control | {
+            x: string | number;
+            y: string | number;
+        })[]): MultiLinePoint[];
+        push(item?: (AbstractMesh | Control | {
+            x: string | number;
+            y: string | number;
+        })): MultiLinePoint;
+        remove(value: number | MultiLinePoint): void;
+        lineWidth: number;
+        horizontalAlignment: number;
+        verticalAlignment: number;
+        protected _getTypeName(): string;
+        _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        _measure(): void;
+        protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        dispose(): void;
+    }
+}

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


+ 118 - 97
dist/preview release/loaders/babylon.glTF1FileLoader.d.ts

@@ -1,8 +1,8 @@
 
 
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
-    * Coordinate system mode that will be used when loading from the gltf file
-    */
+     * Mode that determines the coordinate system to use.
+     */
     enum GLTFLoaderCoordinateSystemMode {
     enum GLTFLoaderCoordinateSystemMode {
         /**
         /**
          * Automatically convert the glTF right-handed data to the appropriate system based on the current coordinate system mode of the scene.
          * Automatically convert the glTF right-handed data to the appropriate system based on the current coordinate system mode of the scene.
@@ -14,8 +14,8 @@ declare module BABYLON {
         FORCE_RIGHT_HANDED = 1,
         FORCE_RIGHT_HANDED = 1,
     }
     }
     /**
     /**
-    * Animation mode that determines which animations should be started when a file is loaded
-    */
+     * Mode that determines what animations will start.
+     */
     enum GLTFLoaderAnimationStartMode {
     enum GLTFLoaderAnimationStartMode {
         /**
         /**
          * No animation will start.
          * No animation will start.
@@ -31,34 +31,34 @@ declare module BABYLON {
         ALL = 2,
         ALL = 2,
     }
     }
     /**
     /**
-    * Loaded gltf data
-    */
+     * Interface that contains the data for the glTF asset.
+     */
     interface IGLTFLoaderData {
     interface IGLTFLoaderData {
         /**
         /**
-        * Loaded json string converted to an object
-        */
+         * JSON that represents the glTF.
+         */
         json: Object;
         json: Object;
         /**
         /**
-        * Loaded ArrayBufferView
-        */
+         * The BIN chunk of a binary glTF
+         */
         bin: Nullable<ArrayBufferView>;
         bin: Nullable<ArrayBufferView>;
     }
     }
     /**
     /**
-    * Gltf extension interface
-    */
+     * Interface for extending the loader.
+     */
     interface IGLTFLoaderExtension {
     interface IGLTFLoaderExtension {
         /**
         /**
          * The name of this extension.
          * The name of this extension.
          */
          */
         readonly name: string;
         readonly name: string;
         /**
         /**
-         * Whether this extension is enabled.
+         * Defines whether this extension is enabled.
          */
          */
         enabled: boolean;
         enabled: boolean;
     }
     }
     /**
     /**
-    * Loading state
-    */
+     * Loader state.
+     */
     enum GLTFLoaderState {
     enum GLTFLoaderState {
         /**
         /**
          * The asset is loading.
          * The asset is loading.
@@ -74,60 +74,67 @@ declare module BABYLON {
         COMPLETE = 2,
         COMPLETE = 2,
     }
     }
     /**
     /**
-    * GLTF loader interface
-    */
+     * Loader interface.
+     */
     interface IGLTFLoader extends IDisposable {
     interface IGLTFLoader extends IDisposable {
         /**
         /**
-        * Coordinate system that will be used when loading from the gltf file
-        */
+         * Mode that determines the coordinate system to use.
+         */
         coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
         coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
         /**
         /**
-        * Animation mode that determines which animations should be started when a file is loaded
-        */
+         * Mode that determines what animations will start.
+         */
         animationStartMode: GLTFLoaderAnimationStartMode;
         animationStartMode: GLTFLoaderAnimationStartMode;
         /**
         /**
-        * If the materials in the file should automatically be compiled
-        */
+         * Defines if the loader should compile materials.
+         */
         compileMaterials: boolean;
         compileMaterials: boolean;
         /**
         /**
-        * If a clip plane should be usede when loading meshes in the file
-        */
+         * Defines if the loader should also compile materials with clip planes.
+         */
         useClipPlane: boolean;
         useClipPlane: boolean;
         /**
         /**
-        * If shadow generators should automatically be compiled
-        */
+         * Defines if the loader should compile shadow generators.
+         */
         compileShadowGenerators: boolean;
         compileShadowGenerators: boolean;
         /**
         /**
-        * Observable that fires each time a mesh is loaded
-        */
+         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
+         */
         onMeshLoadedObservable: Observable<AbstractMesh>;
         onMeshLoadedObservable: Observable<AbstractMesh>;
         /**
         /**
-        * Observable that fires each time a texture is loaded
-        */
+         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
+         */
         onTextureLoadedObservable: Observable<BaseTexture>;
         onTextureLoadedObservable: Observable<BaseTexture>;
         /**
         /**
-       * Observable that fires each time a material is loaded
-       */
+         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
+         */
         onMaterialLoadedObservable: Observable<Material>;
         onMaterialLoadedObservable: Observable<Material>;
         /**
         /**
-        * Observable that fires when the load has completed
-        */
+         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
+         */
+        onCameraLoadedObservable: Observable<Camera>;
+        /**
+         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
+         * For assets with LODs, raised when all of the LODs are complete.
+         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
+         */
         onCompleteObservable: Observable<IGLTFLoader>;
         onCompleteObservable: Observable<IGLTFLoader>;
         /**
         /**
-        * Observable that fires when the loader is disposed
-        */
+         * Observable raised after the loader is disposed.
+         */
         onDisposeObservable: Observable<IGLTFLoader>;
         onDisposeObservable: Observable<IGLTFLoader>;
         /**
         /**
-        * Observable that fire when an extension is loaded
-        */
+         * Observable raised after a loader extension is created.
+         * Set additional options for a loader extension in this event.
+         */
         onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         /**
         /**
-        * Loader state
-        */
+         * Loader state or null if the loader is not active.
+         */
         state: Nullable<GLTFLoaderState>;
         state: Nullable<GLTFLoaderState>;
         /**
         /**
-        * Imports one or more meshes from a loaded gltf file and adds them to the scene
-        */
+         * Imports meshes from the given data and adds them to the scene.
+         */
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{
             meshes: AbstractMesh[];
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             particleSystems: ParticleSystem[];
@@ -135,122 +142,135 @@ declare module BABYLON {
             animationGroups: AnimationGroup[];
             animationGroups: AnimationGroup[];
         }>;
         }>;
         /**
         /**
-        * Imports all objects from a loaded gltf file and adds them to the scene
-        */
+         * Loads all objects from the given data and adds them to the scene.
+         */
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
     }
     }
-    /** File loader to load gltf files into a babylon scene */
+    /**
+     * File loader for loading glTF files into a scene.
+     */
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
     class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
-        /** Creates a gltf 1.0 file loader */
+        /**
+         * Factory function that creates a glTF 1.0 loader
+         */
         static CreateGLTFLoaderV1: () => IGLTFLoader;
         static CreateGLTFLoaderV1: () => IGLTFLoader;
-        /** Creates a gltf 2.0 file loader */
+        /**
+         * Factory function that creates a glTF 2.0 loader
+         */
         static CreateGLTFLoaderV2: () => IGLTFLoader;
         static CreateGLTFLoaderV2: () => IGLTFLoader;
         /**
         /**
-         * Raised when the asset has been parsed.
-         * The data.json property stores the glTF JSON.
-         * The data.bin property stores the BIN chunk from a glTF binary or null if the input is not a glTF binary.
+         * Raised when the asset has been parsed
          */
          */
         onParsedObservable: Observable<IGLTFLoaderData>;
         onParsedObservable: Observable<IGLTFLoaderData>;
         private _onParsedObserver;
         private _onParsedObserver;
-        /** Raised when the asset has been parsed. */
+        /**
+         * Raised when the asset has been parsed
+         */
         onParsed: (loaderData: IGLTFLoaderData) => void;
         onParsed: (loaderData: IGLTFLoaderData) => void;
         /**
         /**
-         * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders. Textures always loads asynchronously. For example, the success callback can compute the bounding information of the loaded meshes when incremental loading is disabled. Defaults to true.
+         * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders.
+         * Textures always loads asynchronously. For example, the success callback can compute the bounding information of the loaded meshes when incremental loading is disabled.
+         * Defaults to true.
          */
          */
         static IncrementalLoading: boolean;
         static IncrementalLoading: boolean;
         /**
         /**
-         * Set this property to true in order to work with homogeneous coordinates, available with some converters and exporters. Defaults to false. See https://en.wikipedia.org/wiki/Homogeneous_coordinates
+         * Set this property to true in order to work with homogeneous coordinates, available with some converters and exporters.
+         * Defaults to false. See https://en.wikipedia.org/wiki/Homogeneous_coordinates.
          */
          */
         static HomogeneousCoordinates: boolean;
         static HomogeneousCoordinates: boolean;
         /**
         /**
-         * The coordinate system mode (AUTO, FORCE_RIGHT_HANDED). Defaults to AUTO.
-         * - AUTO - Automatically convert the glTF right-handed data to the appropriate system based on the current coordinate system mode of the scene.
-         * - FORCE_RIGHT_HANDED - Sets the useRightHandedSystem flag on the scene.
+         * The coordinate system mode. Defaults to AUTO.
          */
          */
         coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
         coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
         /**
         /**
-        * The animation start mode (NONE, FIRST, ALL). Defaults to FIRST.
-        * - NONE - No animation will start.
-        * - FIRST - The first animation will start.
-        * - ALL - All animations will start.
+        * The animation start mode. Defaults to FIRST.
         */
         */
         animationStartMode: GLTFLoaderAnimationStartMode;
         animationStartMode: GLTFLoaderAnimationStartMode;
         /**
         /**
-         * Set to true to compile materials before raising the success callback. Defaults to false.
+         * Defines if the loader should compile materials before raising the success callback. Defaults to false.
          */
          */
         compileMaterials: boolean;
         compileMaterials: boolean;
         /**
         /**
-         * Set to true to also compile materials with clip planes. Defaults to false.
+         * Defines if the loader should also compile materials with clip planes. Defaults to false.
          */
          */
         useClipPlane: boolean;
         useClipPlane: boolean;
         /**
         /**
-         * Set to true to compile shadow generators before raising the success callback. Defaults to false.
+         * Defines if the loader should compile shadow generators before raising the success callback. Defaults to false.
          */
          */
         compileShadowGenerators: boolean;
         compileShadowGenerators: boolean;
         /**
         /**
-         * Raised when the loader creates a mesh after parsing the glTF properties of the mesh.
+         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
         private _onMeshLoadedObserver;
         private _onMeshLoadedObserver;
         /**
         /**
-         * Raised when the loader creates a mesh after parsing the glTF properties of the mesh. (onMeshLoadedObservable is likely desired instead.)
+         * Callback raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
          */
         onMeshLoaded: (mesh: AbstractMesh) => void;
         onMeshLoaded: (mesh: AbstractMesh) => void;
         /**
         /**
-         * Raised when the loader creates a texture after parsing the glTF properties of the texture.
+         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
          */
          */
         readonly onTextureLoadedObservable: Observable<BaseTexture>;
         readonly onTextureLoadedObservable: Observable<BaseTexture>;
         private _onTextureLoadedObserver;
         private _onTextureLoadedObserver;
         /**
         /**
-         * Method called when a texture has been loaded (onTextureLoadedObservable is likely desired instead.)
+         * Callback raised when the loader creates a texture after parsing the glTF properties of the texture.
          */
          */
         onTextureLoaded: (texture: BaseTexture) => void;
         onTextureLoaded: (texture: BaseTexture) => void;
         /**
         /**
-         * Raised when the loader creates a material after parsing the glTF properties of the material.
+         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
          */
          */
         readonly onMaterialLoadedObservable: Observable<Material>;
         readonly onMaterialLoadedObservable: Observable<Material>;
         private _onMaterialLoadedObserver;
         private _onMaterialLoadedObserver;
         /**
         /**
-         * Method when the loader creates a material after parsing the glTF properties of the material. (onMaterialLoadedObservable is likely desired instead.)
+         * Callback raised when the loader creates a material after parsing the glTF properties of the material.
          */
          */
         onMaterialLoaded: (material: Material) => void;
         onMaterialLoaded: (material: Material) => void;
         /**
         /**
-         * Raised when the asset is completely loaded, immediately before the loader is disposed.
+         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
+         */
+        readonly onCameraLoadedObservable: Observable<Camera>;
+        private _onCameraLoadedObserver;
+        /**
+         * Callback raised when the loader creates a camera after parsing the glTF properties of the camera.
+         */
+        onCameraLoaded: (camera: Camera) => void;
+        /**
+         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          */
          */
         readonly onCompleteObservable: Observable<GLTFFileLoader>;
         readonly onCompleteObservable: Observable<GLTFFileLoader>;
         private _onCompleteObserver;
         private _onCompleteObserver;
         /**
         /**
-         * Raised when the asset is completely loaded, immediately before the loader is disposed. (onCompleteObservable is likely desired instead.)
+         * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
          */
          */
         onComplete: () => void;
         onComplete: () => void;
         /**
         /**
-        * Raised after the loader is disposed.
-        */
+         * Observable raised after the loader is disposed.
+         */
         readonly onDisposeObservable: Observable<GLTFFileLoader>;
         readonly onDisposeObservable: Observable<GLTFFileLoader>;
         private _onDisposeObserver;
         private _onDisposeObserver;
         /**
         /**
-         * Raised after the loader is disposed. (onDisposeObservable is likely desired instead.)
+         * Callback raised after the loader is disposed.
          */
          */
         onDispose: () => void;
         onDispose: () => void;
         /**
         /**
-         * Raised after a loader extension is created.
+         * Observable raised after a loader extension is created.
          * Set additional options for a loader extension in this event.
          * Set additional options for a loader extension in this event.
          */
          */
         readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         private _onExtensionLoadedObserver;
         private _onExtensionLoadedObserver;
         /**
         /**
-         * Raised after a loader extension is created. (onExtensionLoadedObservable is likely desired instead.)
+         * Callback raised after a loader extension is created.
          */
          */
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         /**
         /**
          * Returns a promise that resolves when the asset is completely loaded.
          * Returns a promise that resolves when the asset is completely loaded.
-         * @returns A promise that resolves when the asset is completely loaded.
+         * @returns a promise that resolves when the asset is completely loaded.
          */
          */
         whenCompleteAsync(): Promise<void>;
         whenCompleteAsync(): Promise<void>;
         /**
         /**
-         * The loader state (LOADING, READY, COMPLETE) or null if the loader is not active.
+         * The loader state or null if the loader is not active.
          */
          */
         readonly loaderState: Nullable<GLTFLoaderState>;
         readonly loaderState: Nullable<GLTFLoaderState>;
         private _loader;
         private _loader;
@@ -267,14 +287,14 @@ declare module BABYLON {
          */
          */
         dispose(): void;
         dispose(): void;
         /**
         /**
-        * Imports one or more meshes from a loaded gltf file and adds them to the scene
-        * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
-        * @param scene the scene the meshes should be added to
-        * @param data gltf data containing information of the meshes in a loaded file
-        * @param rootUrl root url to load from
-        * @param onProgress event that fires when loading progress has occured
-        * @returns a promise containg the loaded meshes, particles, skeletons and animations
-        */
+         * Imports one or more meshes from the loaded glTF data and adds them to the scene
+         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
+         * @param scene the scene the meshes should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @returns a promise containg the loaded meshes, particles, skeletons and animations
+         */
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
         importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{
             meshes: AbstractMesh[];
             meshes: AbstractMesh[];
             particleSystems: ParticleSystem[];
             particleSystems: ParticleSystem[];
@@ -282,13 +302,13 @@ declare module BABYLON {
             animationGroups: AnimationGroup[];
             animationGroups: AnimationGroup[];
         }>;
         }>;
         /**
         /**
-        * Imports all objects from a loaded gltf file and adds them to the scene
-        * @param scene the scene the objects should be added to
-        * @param data gltf data containing information of the meshes in a loaded file
-        * @param rootUrl root url to load from
-        * @param onProgress event that fires when loading progress has occured
-        * @returns a promise which completes when objects have been loaded to the scene
-        */
+         * Imports all objects from the loaded glTF data and adds them to the scene
+         * @param scene the scene the objects should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @returns a promise which completes when objects have been loaded to the scene
+         */
         loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
         loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
         /**
         /**
          * Load into an asset container.
          * Load into an asset container.
@@ -300,17 +320,17 @@ declare module BABYLON {
          */
          */
         loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
         loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<AssetContainer>;
         /**
         /**
-         * If the data string can be loaded directly
+         * If the data string can be loaded directly.
          * @param data string contianing the file data
          * @param data string contianing the file data
          * @returns if the data can be loaded directly
          * @returns if the data can be loaded directly
          */
          */
         canDirectLoad(data: string): boolean;
         canDirectLoad(data: string): boolean;
         /**
         /**
-         * Rewrites a url by combining a root url and response url
+         * Rewrites a url by combining a root url and response url.
          */
          */
         rewriteRootURL: (rootUrl: string, responseURL?: string) => string;
         rewriteRootURL: (rootUrl: string, responseURL?: string) => string;
         /**
         /**
-         * Instantiates a gltf file loader plugin
+         * Instantiates a glTF file loader plugin.
          * @returns the created plugin
          * @returns the created plugin
          */
          */
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
@@ -727,6 +747,7 @@ declare module BABYLON.GLTF1 {
         onMeshLoadedObservable: Observable<AbstractMesh>;
         onMeshLoadedObservable: Observable<AbstractMesh>;
         onTextureLoadedObservable: Observable<BaseTexture>;
         onTextureLoadedObservable: Observable<BaseTexture>;
         onMaterialLoadedObservable: Observable<Material>;
         onMaterialLoadedObservable: Observable<Material>;
+        onCameraLoadedObservable: Observable<Camera>;
         onCompleteObservable: Observable<IGLTFLoader>;
         onCompleteObservable: Observable<IGLTFLoader>;
         onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         /**
         /**

+ 84 - 58
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -2,8 +2,8 @@
 var BABYLON;
 var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
     /**
     /**
-    * Coordinate system mode that will be used when loading from the gltf file
-    */
+     * Mode that determines the coordinate system to use.
+     */
     var GLTFLoaderCoordinateSystemMode;
     var GLTFLoaderCoordinateSystemMode;
     (function (GLTFLoaderCoordinateSystemMode) {
     (function (GLTFLoaderCoordinateSystemMode) {
         /**
         /**
@@ -16,8 +16,8 @@ var BABYLON;
         GLTFLoaderCoordinateSystemMode[GLTFLoaderCoordinateSystemMode["FORCE_RIGHT_HANDED"] = 1] = "FORCE_RIGHT_HANDED";
         GLTFLoaderCoordinateSystemMode[GLTFLoaderCoordinateSystemMode["FORCE_RIGHT_HANDED"] = 1] = "FORCE_RIGHT_HANDED";
     })(GLTFLoaderCoordinateSystemMode = BABYLON.GLTFLoaderCoordinateSystemMode || (BABYLON.GLTFLoaderCoordinateSystemMode = {}));
     })(GLTFLoaderCoordinateSystemMode = BABYLON.GLTFLoaderCoordinateSystemMode || (BABYLON.GLTFLoaderCoordinateSystemMode = {}));
     /**
     /**
-    * Animation mode that determines which animations should be started when a file is loaded
-    */
+     * Mode that determines what animations will start.
+     */
     var GLTFLoaderAnimationStartMode;
     var GLTFLoaderAnimationStartMode;
     (function (GLTFLoaderAnimationStartMode) {
     (function (GLTFLoaderAnimationStartMode) {
         /**
         /**
@@ -34,8 +34,8 @@ var BABYLON;
         GLTFLoaderAnimationStartMode[GLTFLoaderAnimationStartMode["ALL"] = 2] = "ALL";
         GLTFLoaderAnimationStartMode[GLTFLoaderAnimationStartMode["ALL"] = 2] = "ALL";
     })(GLTFLoaderAnimationStartMode = BABYLON.GLTFLoaderAnimationStartMode || (BABYLON.GLTFLoaderAnimationStartMode = {}));
     })(GLTFLoaderAnimationStartMode = BABYLON.GLTFLoaderAnimationStartMode || (BABYLON.GLTFLoaderAnimationStartMode = {}));
     /**
     /**
-    * Loading state
-    */
+     * Loader state.
+     */
     var GLTFLoaderState;
     var GLTFLoaderState;
     (function (GLTFLoaderState) {
     (function (GLTFLoaderState) {
         /**
         /**
@@ -51,67 +51,66 @@ var BABYLON;
          */
          */
         GLTFLoaderState[GLTFLoaderState["COMPLETE"] = 2] = "COMPLETE";
         GLTFLoaderState[GLTFLoaderState["COMPLETE"] = 2] = "COMPLETE";
     })(GLTFLoaderState = BABYLON.GLTFLoaderState || (BABYLON.GLTFLoaderState = {}));
     })(GLTFLoaderState = BABYLON.GLTFLoaderState || (BABYLON.GLTFLoaderState = {}));
-    /** File loader to load gltf files into a babylon scene */
+    /**
+     * File loader for loading glTF files into a scene.
+     */
     var GLTFFileLoader = /** @class */ (function () {
     var GLTFFileLoader = /** @class */ (function () {
         function GLTFFileLoader() {
         function GLTFFileLoader() {
             // #region Common options
             // #region Common options
             /**
             /**
-             * Raised when the asset has been parsed.
-             * The data.json property stores the glTF JSON.
-             * The data.bin property stores the BIN chunk from a glTF binary or null if the input is not a glTF binary.
+             * Raised when the asset has been parsed
              */
              */
             this.onParsedObservable = new BABYLON.Observable();
             this.onParsedObservable = new BABYLON.Observable();
             // #endregion
             // #endregion
             // #region V2 options
             // #region V2 options
             /**
             /**
-             * The coordinate system mode (AUTO, FORCE_RIGHT_HANDED). Defaults to AUTO.
-             * - AUTO - Automatically convert the glTF right-handed data to the appropriate system based on the current coordinate system mode of the scene.
-             * - FORCE_RIGHT_HANDED - Sets the useRightHandedSystem flag on the scene.
+             * The coordinate system mode. Defaults to AUTO.
              */
              */
             this.coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
             this.coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
             /**
             /**
-            * The animation start mode (NONE, FIRST, ALL). Defaults to FIRST.
-            * - NONE - No animation will start.
-            * - FIRST - The first animation will start.
-            * - ALL - All animations will start.
+            * The animation start mode. Defaults to FIRST.
             */
             */
             this.animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
             this.animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
             /**
             /**
-             * Set to true to compile materials before raising the success callback. Defaults to false.
+             * Defines if the loader should compile materials before raising the success callback. Defaults to false.
              */
              */
             this.compileMaterials = false;
             this.compileMaterials = false;
             /**
             /**
-             * Set to true to also compile materials with clip planes. Defaults to false.
+             * Defines if the loader should also compile materials with clip planes. Defaults to false.
              */
              */
             this.useClipPlane = false;
             this.useClipPlane = false;
             /**
             /**
-             * Set to true to compile shadow generators before raising the success callback. Defaults to false.
+             * Defines if the loader should compile shadow generators before raising the success callback. Defaults to false.
              */
              */
             this.compileShadowGenerators = false;
             this.compileShadowGenerators = false;
             /**
             /**
-             * Raised when the loader creates a mesh after parsing the glTF properties of the mesh.
+             * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
              */
              */
             this.onMeshLoadedObservable = new BABYLON.Observable();
             this.onMeshLoadedObservable = new BABYLON.Observable();
             /**
             /**
-             * Raised when the loader creates a texture after parsing the glTF properties of the texture.
+             * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
              */
              */
             this.onTextureLoadedObservable = new BABYLON.Observable();
             this.onTextureLoadedObservable = new BABYLON.Observable();
             /**
             /**
-             * Raised when the loader creates a material after parsing the glTF properties of the material.
+             * Observable raised when the loader creates a material after parsing the glTF properties of the material.
              */
              */
             this.onMaterialLoadedObservable = new BABYLON.Observable();
             this.onMaterialLoadedObservable = new BABYLON.Observable();
             /**
             /**
-             * Raised when the asset is completely loaded, immediately before the loader is disposed.
+             * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
+             */
+            this.onCameraLoadedObservable = new BABYLON.Observable();
+            /**
+             * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
              * For assets with LODs, raised when all of the LODs are complete.
              * For assets with LODs, raised when all of the LODs are complete.
              * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
              * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
              */
              */
             this.onCompleteObservable = new BABYLON.Observable();
             this.onCompleteObservable = new BABYLON.Observable();
             /**
             /**
-            * Raised after the loader is disposed.
-            */
+             * Observable raised after the loader is disposed.
+             */
             this.onDisposeObservable = new BABYLON.Observable();
             this.onDisposeObservable = new BABYLON.Observable();
             /**
             /**
-             * Raised after a loader extension is created.
+             * Observable raised after a loader extension is created.
              * Set additional options for a loader extension in this event.
              * Set additional options for a loader extension in this event.
              */
              */
             this.onExtensionLoadedObservable = new BABYLON.Observable();
             this.onExtensionLoadedObservable = new BABYLON.Observable();
@@ -130,7 +129,9 @@ var BABYLON;
             };
             };
         }
         }
         Object.defineProperty(GLTFFileLoader.prototype, "onParsed", {
         Object.defineProperty(GLTFFileLoader.prototype, "onParsed", {
-            /** Raised when the asset has been parsed. */
+            /**
+             * Raised when the asset has been parsed
+             */
             set: function (callback) {
             set: function (callback) {
                 if (this._onParsedObserver) {
                 if (this._onParsedObserver) {
                     this.onParsedObservable.remove(this._onParsedObserver);
                     this.onParsedObservable.remove(this._onParsedObserver);
@@ -142,7 +143,7 @@ var BABYLON;
         });
         });
         Object.defineProperty(GLTFFileLoader.prototype, "onMeshLoaded", {
         Object.defineProperty(GLTFFileLoader.prototype, "onMeshLoaded", {
             /**
             /**
-             * Raised when the loader creates a mesh after parsing the glTF properties of the mesh. (onMeshLoadedObservable is likely desired instead.)
+             * Callback raised when the loader creates a mesh after parsing the glTF properties of the mesh.
              */
              */
             set: function (callback) {
             set: function (callback) {
                 if (this._onMeshLoadedObserver) {
                 if (this._onMeshLoadedObserver) {
@@ -155,7 +156,7 @@ var BABYLON;
         });
         });
         Object.defineProperty(GLTFFileLoader.prototype, "onTextureLoaded", {
         Object.defineProperty(GLTFFileLoader.prototype, "onTextureLoaded", {
             /**
             /**
-             * Method called when a texture has been loaded (onTextureLoadedObservable is likely desired instead.)
+             * Callback raised when the loader creates a texture after parsing the glTF properties of the texture.
              */
              */
             set: function (callback) {
             set: function (callback) {
                 if (this._onTextureLoadedObserver) {
                 if (this._onTextureLoadedObserver) {
@@ -168,7 +169,7 @@ var BABYLON;
         });
         });
         Object.defineProperty(GLTFFileLoader.prototype, "onMaterialLoaded", {
         Object.defineProperty(GLTFFileLoader.prototype, "onMaterialLoaded", {
             /**
             /**
-             * Method when the loader creates a material after parsing the glTF properties of the material. (onMaterialLoadedObservable is likely desired instead.)
+             * Callback raised when the loader creates a material after parsing the glTF properties of the material.
              */
              */
             set: function (callback) {
             set: function (callback) {
                 if (this._onMaterialLoadedObserver) {
                 if (this._onMaterialLoadedObserver) {
@@ -179,9 +180,22 @@ var BABYLON;
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
         });
         });
+        Object.defineProperty(GLTFFileLoader.prototype, "onCameraLoaded", {
+            /**
+             * Callback raised when the loader creates a camera after parsing the glTF properties of the camera.
+             */
+            set: function (callback) {
+                if (this._onCameraLoadedObserver) {
+                    this.onCameraLoadedObservable.remove(this._onCameraLoadedObserver);
+                }
+                this._onCameraLoadedObserver = this.onCameraLoadedObservable.add(callback);
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(GLTFFileLoader.prototype, "onComplete", {
         Object.defineProperty(GLTFFileLoader.prototype, "onComplete", {
             /**
             /**
-             * Raised when the asset is completely loaded, immediately before the loader is disposed. (onCompleteObservable is likely desired instead.)
+             * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
              */
              */
             set: function (callback) {
             set: function (callback) {
                 if (this._onCompleteObserver) {
                 if (this._onCompleteObserver) {
@@ -194,7 +208,7 @@ var BABYLON;
         });
         });
         Object.defineProperty(GLTFFileLoader.prototype, "onDispose", {
         Object.defineProperty(GLTFFileLoader.prototype, "onDispose", {
             /**
             /**
-             * Raised after the loader is disposed. (onDisposeObservable is likely desired instead.)
+             * Callback raised after the loader is disposed.
              */
              */
             set: function (callback) {
             set: function (callback) {
                 if (this._onDisposeObserver) {
                 if (this._onDisposeObserver) {
@@ -207,7 +221,7 @@ var BABYLON;
         });
         });
         Object.defineProperty(GLTFFileLoader.prototype, "onExtensionLoaded", {
         Object.defineProperty(GLTFFileLoader.prototype, "onExtensionLoaded", {
             /**
             /**
-             * Raised after a loader extension is created. (onExtensionLoadedObservable is likely desired instead.)
+             * Callback raised after a loader extension is created.
              */
              */
             set: function (callback) {
             set: function (callback) {
                 if (this._onExtensionLoadedObserver) {
                 if (this._onExtensionLoadedObserver) {
@@ -220,7 +234,7 @@ var BABYLON;
         });
         });
         /**
         /**
          * Returns a promise that resolves when the asset is completely loaded.
          * Returns a promise that resolves when the asset is completely loaded.
-         * @returns A promise that resolves when the asset is completely loaded.
+         * @returns a promise that resolves when the asset is completely loaded.
          */
          */
         GLTFFileLoader.prototype.whenCompleteAsync = function () {
         GLTFFileLoader.prototype.whenCompleteAsync = function () {
             var _this = this;
             var _this = this;
@@ -232,7 +246,7 @@ var BABYLON;
         };
         };
         Object.defineProperty(GLTFFileLoader.prototype, "loaderState", {
         Object.defineProperty(GLTFFileLoader.prototype, "loaderState", {
             /**
             /**
-             * The loader state (LOADING, READY, COMPLETE) or null if the loader is not active.
+             * The loader state or null if the loader is not active.
              */
              */
             get: function () {
             get: function () {
                 return this._loader ? this._loader.state : null;
                 return this._loader ? this._loader.state : null;
@@ -251,18 +265,21 @@ var BABYLON;
             this.onMeshLoadedObservable.clear();
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
+            this.onCameraLoadedObservable.clear();
+            this.onCompleteObservable.clear();
+            this.onExtensionLoadedObservable.clear();
             this.onDisposeObservable.notifyObservers(this);
             this.onDisposeObservable.notifyObservers(this);
             this.onDisposeObservable.clear();
             this.onDisposeObservable.clear();
         };
         };
         /**
         /**
-        * Imports one or more meshes from a loaded gltf file and adds them to the scene
-        * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
-        * @param scene the scene the meshes should be added to
-        * @param data gltf data containing information of the meshes in a loaded file
-        * @param rootUrl root url to load from
-        * @param onProgress event that fires when loading progress has occured
-        * @returns a promise containg the loaded meshes, particles, skeletons and animations
-        */
+         * Imports one or more meshes from the loaded glTF data and adds them to the scene
+         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
+         * @param scene the scene the meshes should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @returns a promise containg the loaded meshes, particles, skeletons and animations
+         */
         GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
         GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
             var _this = this;
             var _this = this;
             return Promise.resolve().then(function () {
             return Promise.resolve().then(function () {
@@ -272,13 +289,13 @@ var BABYLON;
             });
             });
         };
         };
         /**
         /**
-        * Imports all objects from a loaded gltf file and adds them to the scene
-        * @param scene the scene the objects should be added to
-        * @param data gltf data containing information of the meshes in a loaded file
-        * @param rootUrl root url to load from
-        * @param onProgress event that fires when loading progress has occured
-        * @returns a promise which completes when objects have been loaded to the scene
-        */
+         * Imports all objects from the loaded glTF data and adds them to the scene
+         * @param scene the scene the objects should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @returns a promise which completes when objects have been loaded to the scene
+         */
         GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
         GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
             var _this = this;
             var _this = this;
             return Promise.resolve().then(function () {
             return Promise.resolve().then(function () {
@@ -312,7 +329,7 @@ var BABYLON;
             });
             });
         };
         };
         /**
         /**
-         * If the data string can be loaded directly
+         * If the data string can be loaded directly.
          * @param data string contianing the file data
          * @param data string contianing the file data
          * @returns if the data can be loaded directly
          * @returns if the data can be loaded directly
          */
          */
@@ -320,7 +337,7 @@ var BABYLON;
             return ((data.indexOf("scene") !== -1) && (data.indexOf("node") !== -1));
             return ((data.indexOf("scene") !== -1) && (data.indexOf("node") !== -1));
         };
         };
         /**
         /**
-         * Instantiates a gltf file loader plugin
+         * Instantiates a glTF file loader plugin.
          * @returns the created plugin
          * @returns the created plugin
          */
          */
         GLTFFileLoader.prototype.createPlugin = function () {
         GLTFFileLoader.prototype.createPlugin = function () {
@@ -375,11 +392,16 @@ var BABYLON;
             loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
             loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
-            loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
+            loader.onCameraLoadedObservable.add(function (camera) { return _this.onCameraLoadedObservable.notifyObservers(camera); });
+            loader.onExtensionLoadedObservable.add(function (extension) {
+                _this.onExtensionLoadedObservable.notifyObservers(extension);
+                _this.onExtensionLoadedObservable.clear();
+            });
             loader.onCompleteObservable.add(function () {
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();
                 _this.onMaterialLoadedObservable.clear();
                 _this.onMaterialLoadedObservable.clear();
+                _this.onCameraLoadedObservable.clear();
                 _this.onCompleteObservable.notifyObservers(_this);
                 _this.onCompleteObservable.notifyObservers(_this);
                 _this.onCompleteObservable.clear();
                 _this.onCompleteObservable.clear();
             });
             });
@@ -507,11 +529,14 @@ var BABYLON;
         // #endregion
         // #endregion
         // #region V1 options
         // #region V1 options
         /**
         /**
-         * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders. Textures always loads asynchronously. For example, the success callback can compute the bounding information of the loaded meshes when incremental loading is disabled. Defaults to true.
+         * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders.
+         * Textures always loads asynchronously. For example, the success callback can compute the bounding information of the loaded meshes when incremental loading is disabled.
+         * Defaults to true.
          */
          */
         GLTFFileLoader.IncrementalLoading = true;
         GLTFFileLoader.IncrementalLoading = true;
         /**
         /**
-         * Set this property to true in order to work with homogeneous coordinates, available with some converters and exporters. Defaults to false. See https://en.wikipedia.org/wiki/Homogeneous_coordinates
+         * Set this property to true in order to work with homogeneous coordinates, available with some converters and exporters.
+         * Defaults to false. See https://en.wikipedia.org/wiki/Homogeneous_coordinates.
          */
          */
         GLTFFileLoader.HomogeneousCoordinates = false;
         GLTFFileLoader.HomogeneousCoordinates = false;
         return GLTFFileLoader;
         return GLTFFileLoader;
@@ -1381,7 +1406,7 @@ var BABYLON;
                 var camera = gltfRuntime.cameras[node.camera];
                 var camera = gltfRuntime.cameras[node.camera];
                 if (camera) {
                 if (camera) {
                     if (camera.type === "orthographic") {
                     if (camera.type === "orthographic") {
-                        var orthoCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
+                        var orthoCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene, false);
                         orthoCamera.name = node.name || "";
                         orthoCamera.name = node.name || "";
                         orthoCamera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;
                         orthoCamera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;
                         orthoCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         orthoCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
@@ -1389,7 +1414,7 @@ var BABYLON;
                     }
                     }
                     else if (camera.type === "perspective") {
                     else if (camera.type === "perspective") {
                         var perspectiveCamera = camera[camera.type];
                         var perspectiveCamera = camera[camera.type];
-                        var persCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
+                        var persCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene, false);
                         persCamera.name = node.name || "";
                         persCamera.name = node.name || "";
                         persCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         persCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
                         if (!perspectiveCamera.aspectRatio) {
                         if (!perspectiveCamera.aspectRatio) {
@@ -1947,6 +1972,7 @@ var BABYLON;
                 this.onMeshLoadedObservable = new BABYLON.Observable();
                 this.onMeshLoadedObservable = new BABYLON.Observable();
                 this.onTextureLoadedObservable = new BABYLON.Observable();
                 this.onTextureLoadedObservable = new BABYLON.Observable();
                 this.onMaterialLoadedObservable = new BABYLON.Observable();
                 this.onMaterialLoadedObservable = new BABYLON.Observable();
+                this.onCameraLoadedObservable = new BABYLON.Observable();
                 this.onCompleteObservable = new BABYLON.Observable();
                 this.onCompleteObservable = new BABYLON.Observable();
                 this.onExtensionLoadedObservable = new BABYLON.Observable();
                 this.onExtensionLoadedObservable = new BABYLON.Observable();
                 /**
                 /**

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


File diff suppressed because it is too large
+ 303 - 339
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts


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


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


File diff suppressed because it is too large
+ 304 - 339
dist/preview release/loaders/babylon.glTFFileLoader.d.ts


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


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


File diff suppressed because it is too large
+ 304 - 339
dist/preview release/loaders/babylonjs.loaders.d.ts


File diff suppressed because it is too large
+ 322 - 239
dist/preview release/loaders/babylonjs.loaders.js


File diff suppressed because it is too large
+ 4 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


File diff suppressed because it is too large
+ 304 - 339
dist/preview release/loaders/babylonjs.loaders.module.d.ts


File diff suppressed because it is too large
+ 505 - 263
dist/preview release/serializers/babylon.glTF2Serializer.d.ts


File diff suppressed because it is too large
+ 1308 - 555
dist/preview release/serializers/babylon.glTF2Serializer.js


File diff suppressed because it is too large
+ 2 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


File diff suppressed because it is too large
+ 505 - 263
dist/preview release/serializers/babylonjs.serializers.d.ts


File diff suppressed because it is too large
+ 1308 - 555
dist/preview release/serializers/babylonjs.serializers.js


File diff suppressed because it is too large
+ 2 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


File diff suppressed because it is too large
+ 505 - 263
dist/preview release/serializers/babylonjs.serializers.module.d.ts


File diff suppressed because it is too large
+ 10972 - 13738
dist/preview release/typedocValidationBaseline.json


File diff suppressed because it is too large
+ 38 - 38
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 1552 - 849
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -14,7 +14,7 @@
 - Added [GlowLayer](https://doc.babylonjs.com/how_to/glow_layer) to easily support glow from emissive materials. Demo [here](http://www.babylonjs.com/demos/GlowLayer/) ([sebavan](https://github.com/sebavan))
 - Added [GlowLayer](https://doc.babylonjs.com/how_to/glow_layer) to easily support glow from emissive materials. Demo [here](http://www.babylonjs.com/demos/GlowLayer/) ([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))
 - 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](https://www.babylonjs-playground.com/frame.html#8F5HYV#9), [MSAA, sharpening, chromatic aberration and grain effect](https://www.babylonjs-playground.com/#Y3C0HQ#146) to the default pipeline ([trevordev](https://github.com/trevordev))
 - Added [depth of field](https://www.babylonjs-playground.com/frame.html#8F5HYV#9), [MSAA, sharpening, chromatic aberration and grain effect](https://www.babylonjs-playground.com/#Y3C0HQ#146) to the default pipeline ([trevordev](https://github.com/trevordev))
-- Added support for [animation weights](http://doc.babylonjs.com/babylon101/animations#animation-weights). Demo [here](https://www.babylonjs-playground.com/#IQN716#9) ([deltakosh](https://github.com/deltakosh))
+- Added support for [animation weights](http://doc.babylonjs.com/babylon101/animations#animation-weights). Demo [here](https://www.babylonjs-playground.com/#LL5BIQ) ([deltakosh](https://github.com/deltakosh))
 - Added [sub emitters for particle system](http://doc.babylonjs.com/babylon101/particles#sub-emitters) which will spawn new particle systems when particles dies. Demo [here](https://www.babylonjs-playground.com/frame.html#9NHBCC#1) ([IbraheemOsama](https://github.com/IbraheemOsama))
 - Added [sub emitters for particle system](http://doc.babylonjs.com/babylon101/particles#sub-emitters) which will spawn new particle systems when particles dies. Demo [here](https://www.babylonjs-playground.com/frame.html#9NHBCC#1) ([IbraheemOsama](https://github.com/IbraheemOsama))
 - New [Babylon.js](http://doc.babylonjs.com/resources/maya) and [glTF](http://doc.babylonjs.com/resources/maya_to_gltf) exporter for Autodesk Maya ([Noalak](https://github.com/Noalak))
 - New [Babylon.js](http://doc.babylonjs.com/resources/maya) and [glTF](http://doc.babylonjs.com/resources/maya_to_gltf) exporter for Autodesk Maya ([Noalak](https://github.com/Noalak))
 - New glTF [serializer](https://github.com/BabylonJS/Babylon.js/tree/master/serializers/src/glTF/2.0). You can now export glTF or glb files directly from a Babylon scene ([kcoley](https://github.com/kcoley))
 - New glTF [serializer](https://github.com/BabylonJS/Babylon.js/tree/master/serializers/src/glTF/2.0). You can now export glTF or glb files directly from a Babylon scene ([kcoley](https://github.com/kcoley))
@@ -114,7 +114,10 @@
 - Added unlit material extension support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
 - Added unlit material extension support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
 - (Viewer) Viewer's declaration file automatically generated ([RaananW](https://github.com/RaananW))
 - (Viewer) Viewer's declaration file automatically generated ([RaananW](https://github.com/RaananW))
 - New serialize and parse functions for effect layers (Highlight and Glow layers) ([julien-moreau](https://github.com/julien-moreau))
 - New serialize and parse functions for effect layers (Highlight and Glow layers) ([julien-moreau](https://github.com/julien-moreau))
+- GUI: Introduced `MultiLine` which will draw lines between any number of meshes, controls and points. [Documentation](http://doc.babylonjs.com/how_to/gui#multiline) ([royibernthal](https://github.com/royibernthal))
 - Added alphaCutOff support for StandardMaterial ([deltakosh](https://github.com/deltakosh))
 - Added alphaCutOff support for StandardMaterial ([deltakosh](https://github.com/deltakosh))
+- Add support for sparse accessors to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
+- Add support for cameras to glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
 
 
 ## Bug fixes
 ## Bug fixes
 
 

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

@@ -278,7 +278,7 @@ module BABYLON.GUI {
             this._fontSet = true;
             this._fontSet = true;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public get _isFontSizeInPercentage(): boolean {
         public get _isFontSizeInPercentage(): boolean {
             return this._fontSize.isPercentage;
             return this._fontSize.isPercentage;
         }
         }
@@ -493,7 +493,7 @@ module BABYLON.GUI {
             return "Control";
             return "Control";
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _resetFontCache(): void {
         public _resetFontCache(): void {
             this._fontSet = true;
             this._fontSet = true;
         }
         }

+ 219 - 0
gui/src/controls/multiLine.ts

@@ -0,0 +1,219 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+
+    export class MultiLine extends Control {
+
+        private _lineWidth: number = 1;
+        private _dash: number[];
+        private _points: Nullable<MultiLinePoint>[];
+
+        private _minX: Nullable<number>;
+        private _minY: Nullable<number>;
+        private _maxX: Nullable<number>;
+        private _maxY: Nullable<number>;
+
+        constructor(public name?: string) {
+            super(name);
+
+            this.isHitTestVisible = false;
+            this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
+            this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
+
+            this._dash = [];
+            this._points = [];
+        }
+
+        public get dash(): Array<number> {
+            return this._dash;
+        }
+
+        public set dash(value: Array<number>) {
+            if (this._dash === value) {
+                return;
+            }
+
+            this._dash = value;
+            this._markAsDirty();
+        }
+
+        public getAt(index: number): MultiLinePoint {
+            if (!this._points[index]) {
+                this._points[index] = new MultiLinePoint(this);
+            }
+
+            return this._points[index] as MultiLinePoint;
+        }
+
+        public onPointUpdate = (): void => {
+            this._markAsDirty();
+        }
+
+        public add(...items: (AbstractMesh | Control | { x: string | number, y: string | number })[]): MultiLinePoint[] {
+            return items.map(item => this.push(item));
+        }
+
+        public push(item?: (AbstractMesh | Control | { x: string | number, y: string | number })): MultiLinePoint {
+            var point: MultiLinePoint = this.getAt(this._points.length);
+
+            if (item == null) return point;
+
+            if (item instanceof AbstractMesh) {
+                point.mesh = item;
+            }
+            else if (item instanceof Control) {
+                point.control = item;
+            }
+            else if (item.x != null && item.y != null) {
+                point.x = item.x;
+                point.y = item.y;
+            }
+
+            return point;
+        }
+
+        public remove(value: number | MultiLinePoint): void {
+            var index: number;
+            
+            if (value instanceof MultiLinePoint) {
+                index = this._points.indexOf(value);
+
+                if (index === -1) {
+                    return;
+                }
+            }
+            else {
+                index = value;
+            }
+            
+            var point: Nullable<MultiLinePoint> = this._points[index];
+
+            if (!point) {
+                return;
+            }
+
+            point.dispose();
+
+            this._points.splice(index, 1);
+        }
+        
+        public get lineWidth(): number {
+            return this._lineWidth;
+        }
+
+        public set lineWidth(value: number) {
+            if (this._lineWidth === value) {
+                return;
+            }
+
+            this._lineWidth = value;
+            this._markAsDirty();
+        }   
+
+        public set horizontalAlignment(value: number) {
+            return;
+        } 
+
+        public set verticalAlignment(value: number) {
+            return;
+        }
+
+        protected _getTypeName(): string {
+            return "MultiLine";
+        }              
+
+        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            context.save();
+
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY){
+                context.shadowColor = this.shadowColor;
+                context.shadowBlur = this.shadowBlur;
+                context.shadowOffsetX = this.shadowOffsetX;
+                context.shadowOffsetY = this.shadowOffsetY;
+            }
+
+            this._applyStates(context);
+
+            if (this._processMeasures(parentMeasure, context)) {
+                context.strokeStyle = this.color;
+                context.lineWidth = this._lineWidth;
+                context.setLineDash(this._dash);
+
+                context.beginPath();
+
+                var first: boolean = true; //first index is not necessarily 0
+
+                this._points.forEach(point => {
+                    if (!point) {
+                        return;
+                    }
+
+                    if (first) {
+                        context.moveTo(point._point.x, point._point.y);
+
+                        first = false;
+                    }
+                    else {
+                        context.lineTo(point._point.x, point._point.y);
+                    }
+                });
+
+                context.stroke();
+            }
+
+            context.restore();
+        }
+
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            this._minX = null;
+            this._minY = null;
+            this._maxX = null;
+            this._maxY = null;
+            
+            this._points.forEach((point, index) => {
+                if (!point) {
+                    return;
+                }
+
+                point.translate();
+
+                if (this._minX == null || point._point.x < this._minX) this._minX = point._point.x;
+                if (this._minY == null || point._point.y < this._minY) this._minY = point._point.y;
+                if (this._maxX == null || point._point.x > this._maxX) this._maxX = point._point.x;
+                if (this._maxY == null || point._point.y > this._maxY) this._maxY = point._point.y;
+            });
+
+            if (this._minX == null) this._minX = 0;
+            if (this._minY == null) this._minY = 0;
+            if (this._maxX == null) this._maxX = 0;
+            if (this._maxY == null) this._maxY = 0;
+        }
+
+        public _measure(): void {
+            if (this._minX == null || this._maxX == null || this._minY == null || this._maxY == null) {
+                return;
+            }
+
+            this._currentMeasure.width = Math.abs(this._maxX - this._minX) + this._lineWidth;
+            this._currentMeasure.height = Math.abs(this._maxY - this._minY) + this._lineWidth;
+        }
+
+        protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            if (this._minX == null || this._minY == null) {
+                return;
+            }
+
+            this._currentMeasure.left = this._minX - this._lineWidth / 2;
+            this._currentMeasure.top = this._minY - this._lineWidth / 2;  
+        }
+
+        public dispose(): void {
+            while (this._points.length > 0) {
+                this.remove(this._points.length - 1);
+            }
+
+            super.dispose();
+        }
+
+    }    
+}

+ 1 - 1
gui/src/controls/textBlock.ts

@@ -224,7 +224,7 @@ module BABYLON.GUI {
             context.fillText(text, this._currentMeasure.left + x, y);
             context.fillText(text, this._currentMeasure.left + x, y);
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
             context.save();
 
 

+ 132 - 0
gui/src/multiLinePoint.ts

@@ -0,0 +1,132 @@
+/// <reference path="../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+
+    export class MultiLinePoint {
+
+        private _multiLine: MultiLine;
+
+        private _x: ValueAndUnit;
+        private _y: ValueAndUnit;
+        private _control: Nullable<Control>;
+        private _mesh: Nullable<AbstractMesh>;
+
+        private _controlObserver: Nullable< Observer<Control> >;
+        private _meshObserver: Nullable< Observer<Camera> >;
+
+        public _point: Vector2;
+
+        constructor(multiLine: MultiLine) {
+            this._multiLine = multiLine;
+
+            this._x = new ValueAndUnit(0);
+            this._y = new ValueAndUnit(0);
+
+            this._point = new Vector2(0, 0);
+        }
+
+        public get x(): string | number {
+            return this._x.toString(this._multiLine._host);
+        }
+
+        public set x(value: string | number) {
+            if (this._x.toString(this._multiLine._host) === value) {
+                return;
+            }
+
+            if (this._x.fromString(value)) {
+                this._multiLine._markAsDirty();
+            }
+        }
+
+        public get y(): string | number {
+            return this._y.toString(this._multiLine._host);
+        }
+
+        public set y(value: string | number) {
+            if (this._y.toString(this._multiLine._host) === value) {
+                return;
+            }
+
+            if (this._y.fromString(value)) {
+                this._multiLine._markAsDirty();
+            }
+        }
+
+        public get control(): Nullable<Control> {
+            return this._control;
+        }
+
+        public set control(value: Nullable<Control>) {
+            if (this._control === value) {
+                return;
+            }
+
+            if (this._control && this._controlObserver) {
+                this._control.onDirtyObservable.remove(this._controlObserver);
+
+                this._controlObserver = null;
+            }
+
+            this._control = value;
+
+            if (this._control) {
+                this._controlObserver = this._control.onDirtyObservable.add(this._multiLine.onPointUpdate);
+            }
+
+            this._multiLine._markAsDirty();
+        }
+
+        public get mesh(): Nullable<AbstractMesh> {
+            return this._mesh;
+        }
+
+        public set mesh(value: Nullable<AbstractMesh>) {
+            if (this._mesh === value) {
+                return;
+            }
+
+            if (this._mesh && this._meshObserver) {
+                this._mesh.getScene().onAfterCameraRenderObservable.remove(this._meshObserver);
+            }
+
+            this._mesh = value;
+
+            if (this._mesh) {
+                this._meshObserver = this._mesh.getScene().onAfterCameraRenderObservable.add(this._multiLine.onPointUpdate);
+            }
+
+            this._multiLine._markAsDirty();
+        }
+
+        public translate(): Vector2 {
+            this._point = this._translatePoint();
+
+            return this._point;
+        }
+
+        private _translatePoint(): Vector2 {
+            if (this._mesh != null) {
+                return this._multiLine._host.getProjectedPosition(this._mesh.getBoundingInfo().boundingSphere.center, this._mesh.getWorldMatrix());
+            }
+            else if (this._control != null) {
+                return new Vector2(this._control.centerX, this._control.centerY);
+            }
+            else {
+                var host: any = this._multiLine._host as any;
+
+                var xValue: number = this._x.getValueInPixel(host, Number(host._canvas.width));
+                var yValue: number = this._y.getValueInPixel(host, Number(host._canvas.height));
+                
+                return new Vector2(xValue, yValue);
+            }
+        }
+
+        public dispose(): void {
+            this.control = null;
+            this.mesh = null;
+        }
+
+    }
+
+}

+ 3 - 2
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -885,7 +885,7 @@ module BABYLON.GLTF1 {
 
 
             if (camera) {
             if (camera) {
                 if (camera.type === "orthographic") {
                 if (camera.type === "orthographic") {
-                    var orthoCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene);
+                    var orthoCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene, false);
 
 
                     orthoCamera.name = node.name || "";
                     orthoCamera.name = node.name || "";
                     orthoCamera.mode = Camera.ORTHOGRAPHIC_CAMERA;
                     orthoCamera.mode = Camera.ORTHOGRAPHIC_CAMERA;
@@ -895,7 +895,7 @@ module BABYLON.GLTF1 {
                 }
                 }
                 else if (camera.type === "perspective") {
                 else if (camera.type === "perspective") {
                     var perspectiveCamera: IGLTFCameraPerspective = (<any>camera)[camera.type];
                     var perspectiveCamera: IGLTFCameraPerspective = (<any>camera)[camera.type];
-                    var persCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene);
+                    var persCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene, false);
 
 
                     persCamera.name = node.name || "";
                     persCamera.name = node.name || "";
                     persCamera.attachControl(<HTMLElement>gltfRuntime.scene.getEngine().getRenderingCanvas());
                     persCamera.attachControl(<HTMLElement>gltfRuntime.scene.getEngine().getRenderingCanvas());
@@ -1573,6 +1573,7 @@ module BABYLON.GLTF1 {
         public onMeshLoadedObservable = new Observable<AbstractMesh>();
         public onMeshLoadedObservable = new Observable<AbstractMesh>();
         public onTextureLoadedObservable = new Observable<BaseTexture>();
         public onTextureLoadedObservable = new Observable<BaseTexture>();
         public onMaterialLoadedObservable = new Observable<Material>();
         public onMaterialLoadedObservable = new Observable<Material>();
+        public onCameraLoadedObservable = new Observable<Camera>();
         public onCompleteObservable = new Observable<IGLTFLoader>();
         public onCompleteObservable = new Observable<IGLTFLoader>();
         public onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
         public onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
 
 

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

@@ -1,9 +1,6 @@
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 
 
-/** Module defining extensions to gltf */
 module BABYLON.GLTF2.Extensions {
 module BABYLON.GLTF2.Extensions {
-    // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression
-
     const NAME = "KHR_draco_mesh_compression";
     const NAME = "KHR_draco_mesh_compression";
 
 
     interface IKHRDracoMeshCompression {
     interface IKHRDracoMeshCompression {
@@ -11,10 +8,13 @@ module BABYLON.GLTF2.Extensions {
         attributes: { [name: string]: number };
         attributes: { [name: string]: number };
     }
     }
 
 
-    interface ILoaderBufferViewDraco extends ILoaderBufferView {
+    interface ILoaderBufferViewDraco extends _ILoaderBufferView {
         _dracoBabylonGeometry?: Promise<Geometry>;
         _dracoBabylonGeometry?: Promise<Geometry>;
     }
     }
 
 
+    /**
+     * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
+     */
     export class KHR_draco_mesh_compression extends GLTFLoaderExtension {
     export class KHR_draco_mesh_compression extends GLTFLoaderExtension {
         public readonly name = NAME;
         public readonly name = NAME;
 
 
@@ -37,7 +37,7 @@ module BABYLON.GLTF2.Extensions {
             super.dispose();
             super.dispose();
         }
         }
 
 
-        protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> {
+        protected _loadVertexDataAsync(context: string, primitive: _ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> {
             return this._loadExtensionAsync<IKHRDracoMeshCompression, Geometry>(context, primitive, (extensionContext, extension) => {
             return this._loadExtensionAsync<IKHRDracoMeshCompression, Geometry>(context, primitive, (extensionContext, extension) => {
                 if (primitive.mode != undefined) {
                 if (primitive.mode != undefined) {
                     if (primitive.mode !== MeshPrimitiveMode.TRIANGLE_STRIP &&
                     if (primitive.mode !== MeshPrimitiveMode.TRIANGLE_STRIP &&

+ 5 - 4
loaders/src/glTF/2.0/Extensions/KHR_lights.ts

@@ -1,8 +1,6 @@
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 
 
 module BABYLON.GLTF2.Extensions {
 module BABYLON.GLTF2.Extensions {
-    // https://github.com/MiiBond/glTF/tree/khr_lights_v1/extensions/Khronos/KHR_lights
-
     const NAME = "KHR_lights";
     const NAME = "KHR_lights";
 
 
     enum LightType {
     enum LightType {
@@ -31,10 +29,13 @@ module BABYLON.GLTF2.Extensions {
         lights: ILight[];
         lights: ILight[];
     }
     }
 
 
+    /**
+     * [Specification](https://github.com/MiiBond/glTF/tree/khr_lights_v1/extensions/Khronos/KHR_lights) (Experimental)
+     */
     export class KHR_lights extends GLTFLoaderExtension {
     export class KHR_lights extends GLTFLoaderExtension {
         public readonly name = NAME;
         public readonly name = NAME;
 
 
-        protected _loadSceneAsync(context: string, scene: ILoaderScene): Nullable<Promise<void>> { 
+        protected _loadSceneAsync(context: string, scene: _ILoaderScene): Nullable<Promise<void>> { 
             return this._loadExtensionAsync<ILightReference>(context, scene, (extensionContext, extension) => {
             return this._loadExtensionAsync<ILightReference>(context, scene, (extensionContext, extension) => {
                 const promise = this._loader._loadSceneAsync(extensionContext, scene);
                 const promise = this._loader._loadSceneAsync(extensionContext, scene);
 
 
@@ -49,7 +50,7 @@ module BABYLON.GLTF2.Extensions {
             });
             });
         }
         }
 
 
-        protected _loadNodeAsync(context: string, node: ILoaderNode): Nullable<Promise<void>> { 
+        protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>> { 
             return this._loadExtensionAsync<ILightReference>(context, node, (extensionContext, extension) => {
             return this._loadExtensionAsync<ILightReference>(context, node, (extensionContext, extension) => {
                 const promise = this._loader._loadNodeAsync(extensionContext, node);
                 const promise = this._loader._loadNodeAsync(extensionContext, node);
 
 

+ 5 - 4
loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts

@@ -1,8 +1,6 @@
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 
 
 module BABYLON.GLTF2.Extensions {
 module BABYLON.GLTF2.Extensions {
-    // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness
-
     const NAME = "KHR_materials_pbrSpecularGlossiness";
     const NAME = "KHR_materials_pbrSpecularGlossiness";
 
 
     interface IKHRMaterialsPbrSpecularGlossiness {
     interface IKHRMaterialsPbrSpecularGlossiness {
@@ -13,10 +11,13 @@ module BABYLON.GLTF2.Extensions {
         specularGlossinessTexture: ITextureInfo;
         specularGlossinessTexture: ITextureInfo;
     }
     }
 
 
+    /**
+     * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness)
+     */
     export class KHR_materials_pbrSpecularGlossiness extends GLTFLoaderExtension {
     export class KHR_materials_pbrSpecularGlossiness extends GLTFLoaderExtension {
         public readonly name = NAME;
         public readonly name = NAME;
 
 
-        protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
             return this._loadExtensionAsync<IKHRMaterialsPbrSpecularGlossiness>(context, material, (extensionContext, extension) => {
             return this._loadExtensionAsync<IKHRMaterialsPbrSpecularGlossiness>(context, material, (extensionContext, extension) => {
                 material._babylonData = material._babylonData || {};
                 material._babylonData = material._babylonData || {};
                 let babylonData = material._babylonData[babylonDrawMode];
                 let babylonData = material._babylonData[babylonDrawMode];
@@ -47,7 +48,7 @@ module BABYLON.GLTF2.Extensions {
             });
             });
         }
         }
 
 
-        private _loadSpecularGlossinessPropertiesAsync(context: string, material: ILoaderMaterial, properties: IKHRMaterialsPbrSpecularGlossiness, babylonMaterial: PBRMaterial): Promise<void> {
+        private _loadSpecularGlossinessPropertiesAsync(context: string, material: _ILoaderMaterial, properties: IKHRMaterialsPbrSpecularGlossiness, babylonMaterial: PBRMaterial): Promise<void> {
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
             if (properties.diffuseFactor) {
             if (properties.diffuseFactor) {

+ 5 - 4
loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts

@@ -1,14 +1,15 @@
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 
 
 module BABYLON.GLTF2.Extensions {
 module BABYLON.GLTF2.Extensions {
-    // https://github.com/donmccurdy/glTF/tree/feat-khr-materials-cmnConstant/extensions/2.0/Khronos/KHR_materials_unlit
-
     const NAME = "KHR_materials_unlit";
     const NAME = "KHR_materials_unlit";
 
 
+    /**
+     * [Specification](https://github.com/donmccurdy/glTF/tree/feat-khr-materials-cmnConstant/extensions/2.0/Khronos/KHR_materials_unlit) (Experimental)
+     */
     export class KHR_materials_unlit extends GLTFLoaderExtension {
     export class KHR_materials_unlit extends GLTFLoaderExtension {
         public readonly name = NAME;
         public readonly name = NAME;
 
 
-        protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
             return this._loadExtensionAsync<{}>(context, material, () => {
             return this._loadExtensionAsync<{}>(context, material, () => {
                 material._babylonData = material._babylonData || {};
                 material._babylonData = material._babylonData || {};
                 let babylonData = material._babylonData[babylonDrawMode];
                 let babylonData = material._babylonData[babylonDrawMode];
@@ -37,7 +38,7 @@ module BABYLON.GLTF2.Extensions {
             });
             });
         }
         }
 
 
-        private _loadUnlitPropertiesAsync(context: string, material: ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
+        private _loadUnlitPropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
             // Ensure metallic workflow
             // Ensure metallic workflow

+ 7 - 6
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -1,14 +1,15 @@
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 
 
 module BABYLON.GLTF2.Extensions {
 module BABYLON.GLTF2.Extensions {
-    // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod
-
     const NAME = "MSFT_lod";
     const NAME = "MSFT_lod";
 
 
     interface IMSFTLOD {
     interface IMSFTLOD {
         ids: number[];
         ids: number[];
     }
     }
 
 
+    /**
+     * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
+     */
     export class MSFT_lod extends GLTFLoaderExtension {
     export class MSFT_lod extends GLTFLoaderExtension {
         public readonly name = NAME;
         public readonly name = NAME;
 
 
@@ -17,13 +18,13 @@ module BABYLON.GLTF2.Extensions {
          */
          */
         public maxLODsToLoad = Number.MAX_VALUE;
         public maxLODsToLoad = Number.MAX_VALUE;
 
 
-        private _loadingNodeLOD: Nullable<ILoaderNode> = null;
+        private _loadingNodeLOD: Nullable<_ILoaderNode> = null;
         private _loadNodeSignals: { [nodeIndex: number]: Deferred<void> } = {};
         private _loadNodeSignals: { [nodeIndex: number]: Deferred<void> } = {};
 
 
-        private _loadingMaterialLOD: Nullable<ILoaderMaterial> = null;
+        private _loadingMaterialLOD: Nullable<_ILoaderMaterial> = null;
         private _loadMaterialSignals: { [materialIndex: number]: Deferred<void> } = {};
         private _loadMaterialSignals: { [materialIndex: number]: Deferred<void> } = {};
 
 
-        protected _loadNodeAsync(context: string, node: ILoaderNode): Nullable<Promise<void>> {
+        protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>> {
             return this._loadExtensionAsync<IMSFTLOD>(context, node, (extensionContext, extension) => {
             return this._loadExtensionAsync<IMSFTLOD>(context, node, (extensionContext, extension) => {
                 let firstPromise: Promise<void>;
                 let firstPromise: Promise<void>;
 
 
@@ -71,7 +72,7 @@ module BABYLON.GLTF2.Extensions {
             });
             });
         }
         }
 
 
-        protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
             // Don't load material LODs if already loading a node LOD.
             // Don't load material LODs if already loading a node LOD.
             if (this._loadingNodeLOD) {
             if (this._loadingNodeLOD) {
                 return null;
                 return null;

+ 298 - 236
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -1,8 +1,8 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 
 
 /**
 /**
-* Defines the GLTF2 module used to import/export GLTF 2.0 files
-*/
+ * Defines the module used to import/export glTF 2.0 assets
+ */
 module BABYLON.GLTF2 {
 module BABYLON.GLTF2 {
     interface IFileRequestInfo extends IFileRequest {
     interface IFileRequestInfo extends IFileRequest {
         _lengthComputable?: boolean;
         _lengthComputable?: boolean;
@@ -10,37 +10,23 @@ module BABYLON.GLTF2 {
         _total?: number;
         _total?: number;
     }
     }
 
 
-    /**
-    * Interface for a meterial with a constructor
-    */
-    export interface MaterialConstructor<T extends Material> {
-        /**
-        * The material class
-        */
+    /** @hidden */
+    export interface _MaterialConstructor<T extends Material> {
         readonly prototype: T;
         readonly prototype: T;
-        /**
-        * Instatiates a material
-        * @param name name of the material
-        * @param scene the scene the material will be added to
-        */
         new(name: string, scene: Scene): T;
         new(name: string, scene: Scene): T;
     }
     }
 
 
     /**
     /**
-    * Used to load from a GLTF2 file
-    */
+     * Loader for loading a glTF 2.0 asset
+     */
     export class GLTFLoader implements IGLTFLoader {
     export class GLTFLoader implements IGLTFLoader {
-        /**
-        * @ignore
-        */
-        public _gltf: ILoaderGLTF;
-        /**
-        * @ignore
-        */
+        /** @hidden */
+        public _gltf: _ILoaderGLTF;
+
+        /** @hidden */
         public _babylonScene: Scene;
         public _babylonScene: Scene;
-        /**
-        * @ignore
-        */
+
+        /** @hidden */
         public _completePromises = new Array<Promise<void>>();
         public _completePromises = new Array<Promise<void>>();
 
 
         private _disposed = false;
         private _disposed = false;
@@ -48,18 +34,15 @@ module BABYLON.GLTF2 {
         private _extensions: { [name: string]: GLTFLoaderExtension } = {};
         private _extensions: { [name: string]: GLTFLoaderExtension } = {};
         private _rootUrl: string;
         private _rootUrl: string;
         private _rootBabylonMesh: Mesh;
         private _rootBabylonMesh: Mesh;
-        private _defaultSampler = {} as ILoaderSampler;
+        private _defaultSampler = {} as _ILoaderSampler;
         private _defaultBabylonMaterials: { [drawMode: number]: PBRMaterial } = {};
         private _defaultBabylonMaterials: { [drawMode: number]: PBRMaterial } = {};
         private _progressCallback?: (event: SceneLoaderProgressEvent) => void;
         private _progressCallback?: (event: SceneLoaderProgressEvent) => void;
         private _requests = new Array<IFileRequestInfo>();
         private _requests = new Array<IFileRequestInfo>();
 
 
         private static _Names = new Array<string>();
         private static _Names = new Array<string>();
         private static _Factories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
         private static _Factories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
-        /**
-        * @ignore, registers the loader
-        * @param name name of the loader
-        * @param factory function that converts a loader to a loader extension
-        */
+
+        /** @hidden */
         public static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void {
         public static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void {
             if (GLTFLoader._Factories[name]) {
             if (GLTFLoader._Factories[name]) {
                 Tools.Error(`Extension with the name '${name}' already exists`);
                 Tools.Error(`Extension with the name '${name}' already exists`);
@@ -73,61 +56,79 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-        * Coordinate system that will be used when loading from the gltf file
-        */
+         * Mode that determines the coordinate system to use.
+         */
         public coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
         public coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
+
         /**
         /**
-        * Animation mode that determines which animations should be started when a file is loaded
-        */
+         * Mode that determines what animations will start.
+         */
         public animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
         public animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
+
         /**
         /**
-        * If the materials in the file should automatically be compiled
-        */
+         * Defines if the loader should compile materials.
+         */
         public compileMaterials = false;
         public compileMaterials = false;
+
         /**
         /**
-        * If a clip plane should be usede when loading meshes in the file
-        */
+         * Defines if the loader should also compile materials with clip planes.
+         */
         public useClipPlane = false;
         public useClipPlane = false;
+
         /**
         /**
-        * If shadow generators should automatically be compiled
-        */
+         * Defines if the loader should compile shadow generators.
+         */
         public compileShadowGenerators = false;
         public compileShadowGenerators = false;
 
 
         /**
         /**
-        * Observable that fires when the loader is disposed
-        */
-        public readonly onDisposeObservable = new Observable<IGLTFLoader>();
-        /**
-        * Observable that fires each time a mesh is loaded
-        */
+         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
+         */
         public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
         public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
+
         /**
         /**
-        * Observable that fires each time a texture is loaded
-        */
+         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
+         */
         public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
         public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
+
         /**
         /**
-        * Observable that fires each time a material is loaded
-        */
+         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
+         */
         public readonly onMaterialLoadedObservable = new Observable<Material>();
         public readonly onMaterialLoadedObservable = new Observable<Material>();
+
         /**
         /**
-        * Observable that fires each time an extension is loaded
-        */
-        public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
+         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
+         */
+        public readonly onCameraLoadedObservable = new Observable<Camera>();
+
         /**
         /**
-        * Observable that fires when the load has completed
-        */
+         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
+         * For assets with LODs, raised when all of the LODs are complete.
+         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
+         */
         public readonly onCompleteObservable = new Observable<IGLTFLoader>();
         public readonly onCompleteObservable = new Observable<IGLTFLoader>();
 
 
         /**
         /**
-        * The current state of the loader
-        */
+         * Observable raised after the loader is disposed.
+         */
+        public readonly onDisposeObservable = new Observable<IGLTFLoader>();
+
+        /**
+         * Observable raised after a loader extension is created.
+         * Set additional options for a loader extension in this event.
+         */
+        public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
+
+
+        /**
+         * Loader state or null if the loader is not active.
+         */
         public get state(): Nullable<GLTFLoaderState> {
         public get state(): Nullable<GLTFLoaderState> {
             return this._state;
             return this._state;
         }
         }
 
 
         /**
         /**
-        * Disposes of the loader
-        */
+         * Disposes the loader, releases resources during load, and cancels any outstanding requests.
+         */
         public dispose(): void {
         public dispose(): void {
             if (this._disposed) {
             if (this._disposed) {
                 return;
                 return;
@@ -142,20 +143,20 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-        * Imports one or more meshes from a loaded gltf file and adds them to the scene
-        * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
-        * @param scene the scene the meshes should be added to
-        * @param data gltf data containing information of the meshes in a loaded file
-        * @param rootUrl root url to load from
-        * @param onProgress event that fires when loading progress has occured
-        * @returns a promise containg the loaded meshes, particles, skeletons and animations
-        */
+         * Imports one or more meshes from the loaded glTF data and adds them to the scene
+         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
+         * @param scene the scene the meshes should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @returns a promise containg the loaded meshes, particles, skeletons and animations
+         */
         public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
         public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
             return Promise.resolve().then(() => {
             return Promise.resolve().then(() => {
-                let nodes: Nullable<Array<ILoaderNode>> = null;
+                let nodes: Nullable<Array<_ILoaderNode>> = null;
 
 
                 if (meshesNames) {
                 if (meshesNames) {
-                    const nodeMap: { [name: string]: ILoaderNode } = {};
+                    const nodeMap: { [name: string]: _ILoaderNode } = {};
                     if (this._gltf.nodes) {
                     if (this._gltf.nodes) {
                         for (const node of this._gltf.nodes) {
                         for (const node of this._gltf.nodes) {
                             if (node.name) {
                             if (node.name) {
@@ -187,18 +188,18 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-        * Imports all objects from a loaded gltf file and adds them to the scene
-        * @param scene the scene the objects should be added to
-        * @param data gltf data containing information of the meshes in a loaded file
-        * @param rootUrl root url to load from
-        * @param onProgress event that fires when loading progress has occured
-        * @returns a promise which completes when objects have been loaded to the scene
-        */
+         * Imports all objects from the loaded glTF data and adds them to the scene
+         * @param scene the scene the objects should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @returns a promise which completes when objects have been loaded to the scene
+         */
         public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
         public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
             return this._loadAsync(null, scene, data, rootUrl, onProgress);
             return this._loadAsync(null, scene, data, rootUrl, onProgress);
         }
         }
 
 
-        private _loadAsync(nodes: Nullable<Array<ILoaderNode>>, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
+        private _loadAsync(nodes: Nullable<Array<_ILoaderNode>>, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
             return Promise.resolve().then(() => {
             return Promise.resolve().then(() => {
                 this._loadExtensions();
                 this._loadExtensions();
 
 
@@ -271,7 +272,7 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         private _loadData(data: IGLTFLoaderData): void {
         private _loadData(data: IGLTFLoaderData): void {
-            this._gltf = data.json as ILoaderGLTF;
+            this._gltf = data.json as _ILoaderGLTF;
             this._setupData();
             this._setupData();
 
 
             if (data.bin) {
             if (data.bin) {
@@ -291,19 +292,19 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         private _setupData(): void {
         private _setupData(): void {
-            ArrayItem.Assign(this._gltf.accessors);
-            ArrayItem.Assign(this._gltf.animations);
-            ArrayItem.Assign(this._gltf.buffers);
-            ArrayItem.Assign(this._gltf.bufferViews);
-            ArrayItem.Assign(this._gltf.cameras);
-            ArrayItem.Assign(this._gltf.images);
-            ArrayItem.Assign(this._gltf.materials);
-            ArrayItem.Assign(this._gltf.meshes);
-            ArrayItem.Assign(this._gltf.nodes);
-            ArrayItem.Assign(this._gltf.samplers);
-            ArrayItem.Assign(this._gltf.scenes);
-            ArrayItem.Assign(this._gltf.skins);
-            ArrayItem.Assign(this._gltf.textures);
+            _ArrayItem.Assign(this._gltf.accessors);
+            _ArrayItem.Assign(this._gltf.animations);
+            _ArrayItem.Assign(this._gltf.buffers);
+            _ArrayItem.Assign(this._gltf.bufferViews);
+            _ArrayItem.Assign(this._gltf.cameras);
+            _ArrayItem.Assign(this._gltf.images);
+            _ArrayItem.Assign(this._gltf.materials);
+            _ArrayItem.Assign(this._gltf.meshes);
+            _ArrayItem.Assign(this._gltf.nodes);
+            _ArrayItem.Assign(this._gltf.samplers);
+            _ArrayItem.Assign(this._gltf.scenes);
+            _ArrayItem.Assign(this._gltf.skins);
+            _ArrayItem.Assign(this._gltf.textures);
 
 
             if (this._gltf.nodes) {
             if (this._gltf.nodes) {
                 const nodeParents: { [index: number]: number } = {};
                 const nodeParents: { [index: number]: number } = {};
@@ -334,11 +335,11 @@ module BABYLON.GLTF2 {
             }
             }
         }
         }
 
 
-        private _createRootNode(): ILoaderNode {
+        private _createRootNode(): _ILoaderNode {
             this._rootBabylonMesh = new Mesh("__root__", this._babylonScene);
             this._rootBabylonMesh = new Mesh("__root__", this._babylonScene);
             this._rootBabylonMesh.setEnabled(false);
             this._rootBabylonMesh.setEnabled(false);
 
 
-            const rootNode = { _babylonMesh: this._rootBabylonMesh } as ILoaderNode;
+            const rootNode = { _babylonMesh: this._rootBabylonMesh } as _ILoaderNode;
             switch (this.coordinateSystemMode) {
             switch (this.coordinateSystemMode) {
                 case GLTFLoaderCoordinateSystemMode.AUTO: {
                 case GLTFLoaderCoordinateSystemMode.AUTO: {
                     if (!this._babylonScene.useRightHandedSystem) {
                     if (!this._babylonScene.useRightHandedSystem) {
@@ -361,7 +362,7 @@ module BABYLON.GLTF2 {
             return rootNode;
             return rootNode;
         }
         }
 
 
-        private _loadNodesAsync(nodes: ILoaderNode[], ): Promise<void> {
+        private _loadNodesAsync(nodes: _ILoaderNode[], ): Promise<void> {
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
             for (let node of nodes) {
             for (let node of nodes) {
@@ -373,10 +374,8 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        /**
-        * @ignore
-        */
-        public _loadSceneAsync(context: string, scene: ILoaderScene): Promise<void> {
+        /** @hidden */
+        public _loadSceneAsync(context: string, scene: _ILoaderScene): Promise<void> {
             const promise = GLTFLoaderExtension._LoadSceneAsync(this, context, scene);
             const promise = GLTFLoaderExtension._LoadSceneAsync(this, context, scene);
             if (promise) {
             if (promise) {
                 return promise;
                 return promise;
@@ -394,7 +393,7 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        private _forEachPrimitive(node: ILoaderNode, callback: (babylonMesh: Mesh) => void): void {
+        private _forEachPrimitive(node: _ILoaderNode, callback: (babylonMesh: Mesh) => void): void {
             if (node._primitiveBabylonMeshes) {
             if (node._primitiveBabylonMeshes) {
                 for (const babylonMesh of node._primitiveBabylonMeshes) {
                 for (const babylonMesh of node._primitiveBabylonMeshes) {
                     callback(babylonMesh);
                     callback(babylonMesh);
@@ -486,10 +485,8 @@ module BABYLON.GLTF2 {
             }
             }
         }
         }
 
 
-        /**
-        * @ignore
-        */
-        public _loadNodeAsync(context: string, node: ILoaderNode): Promise<void> {
+        /** @hidden */
+        public _loadNodeAsync(context: string, node: _ILoaderNode): Promise<void> {
             const promise = GLTFLoaderExtension._LoadNodeAsync(this, context, node);
             const promise = GLTFLoaderExtension._LoadNodeAsync(this, context, node);
             if (promise) {
             if (promise) {
                 return promise;
                 return promise;
@@ -514,6 +511,11 @@ module BABYLON.GLTF2 {
                 promises.push(this._loadMeshAsync(`#/meshes/${mesh._index}`, node, mesh, babylonMesh));
                 promises.push(this._loadMeshAsync(`#/meshes/${mesh._index}`, node, mesh, babylonMesh));
             }
             }
 
 
+            if (node.camera != undefined) {
+                const camera = GLTFLoader._GetProperty(`${context}/camera`, this._gltf.cameras, node.camera);
+                this._loadCamera(`#/cameras/${camera._index}`, camera, babylonMesh);
+            }
+
             if (node.children) {
             if (node.children) {
                 for (const index of node.children) {
                 for (const index of node.children) {
                     const childNode = GLTFLoader._GetProperty(`${context}/children/${index}`, this._gltf.nodes, index);
                     const childNode = GLTFLoader._GetProperty(`${context}/children/${index}`, this._gltf.nodes, index);
@@ -526,7 +528,7 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        private _loadMeshAsync(context: string, node: ILoaderNode, mesh: ILoaderMesh, babylonMesh: Mesh): Promise<void> {
+        private _loadMeshAsync(context: string, node: _ILoaderNode, mesh: _ILoaderMesh, babylonMesh: Mesh): Promise<void> {
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
             const primitives = mesh.primitives;
             const primitives = mesh.primitives;
@@ -534,7 +536,7 @@ module BABYLON.GLTF2 {
                 throw new Error(`${context}: Primitives are missing`);
                 throw new Error(`${context}: Primitives are missing`);
             }
             }
 
 
-            ArrayItem.Assign(primitives);
+            _ArrayItem.Assign(primitives);
             if (primitives.length === 1) {
             if (primitives.length === 1) {
                 const primitive = primitives[0];
                 const primitive = primitives[0];
                 promises.push(this._loadPrimitiveAsync(`${context}/primitives/${primitive._index}`, node, mesh, primitive, babylonMesh));
                 promises.push(this._loadPrimitiveAsync(`${context}/primitives/${primitive._index}`, node, mesh, primitive, babylonMesh));
@@ -561,7 +563,7 @@ module BABYLON.GLTF2 {
             });
             });
         }
         }
 
 
-        private _loadPrimitiveAsync(context: string, node: ILoaderNode, mesh: ILoaderMesh, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Promise<void> {
+        private _loadPrimitiveAsync(context: string, node: _ILoaderNode, mesh: _ILoaderMesh, primitive: _ILoaderMeshPrimitive, babylonMesh: Mesh): Promise<void> {
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
             this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
             this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
@@ -585,7 +587,7 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        private _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Promise<Geometry> {
+        private _loadVertexDataAsync(context: string, primitive: _ILoaderMeshPrimitive, babylonMesh: Mesh): Promise<Geometry> {
             const promise = GLTFLoaderExtension._LoadVertexDataAsync(this, context, primitive, babylonMesh);
             const promise = GLTFLoaderExtension._LoadVertexDataAsync(this, context, primitive, babylonMesh);
             if (promise) {
             if (promise) {
                 return promise;
                 return promise;
@@ -605,12 +607,12 @@ module BABYLON.GLTF2 {
             }
             }
             else {
             else {
                 const accessor = GLTFLoader._GetProperty(context + "/indices", this._gltf.accessors, primitive.indices);
                 const accessor = GLTFLoader._GetProperty(context + "/indices", this._gltf.accessors, primitive.indices);
-                promises.push(this._loadAccessorAsync("#/accessors/" + accessor._index, accessor).then(data => {
-                    babylonGeometry.setIndices(data as IndicesArray);
+                promises.push(this._loadIndicesAccessorAsync("#/accessors/" + accessor._index, accessor).then(data => {
+                    babylonGeometry.setIndices(data);
                 }));
                 }));
             }
             }
 
 
-            const loadAttribute = (attribute: string, kind: string, callback?: (accessor: ILoaderAccessor) => void) => {
+            const loadAttribute = (attribute: string, kind: string, callback?: (accessor: _ILoaderAccessor) => void) => {
                 if (attributes[attribute] == undefined) {
                 if (attributes[attribute] == undefined) {
                     return;
                     return;
                 }
                 }
@@ -648,7 +650,7 @@ module BABYLON.GLTF2 {
             });
             });
         }
         }
 
 
-        private _createMorphTargets(context: string, node: ILoaderNode, mesh: ILoaderMesh, primitive: IMeshPrimitive, babylonMesh: Mesh): void {
+        private _createMorphTargets(context: string, node: _ILoaderNode, mesh: _ILoaderMesh, primitive: IMeshPrimitive, babylonMesh: Mesh): void {
             if (!primitive.targets) {
             if (!primitive.targets) {
                 return;
                 return;
             }
             }
@@ -698,11 +700,7 @@ module BABYLON.GLTF2 {
                 }
                 }
 
 
                 const accessor = GLTFLoader._GetProperty(`${context}/${attribute}`, this._gltf.accessors, attributes[attribute]);
                 const accessor = GLTFLoader._GetProperty(`${context}/${attribute}`, this._gltf.accessors, attributes[attribute]);
-                promises.push(this._loadAccessorAsync(`#/accessors/${accessor._index}`, accessor).then(data => {
-                    if (!(data instanceof Float32Array)) {
-                        throw new Error(`${context}: Morph target accessor must have float data`);
-                    }
-
+                promises.push(this._loadFloatAccessorAsync(`#/accessors/${accessor._index}`, accessor).then(data => {
                     setData(babylonVertexBuffer, data);
                     setData(babylonVertexBuffer, data);
                 }));
                 }));
             };
             };
@@ -739,7 +737,7 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        private static _LoadTransform(node: ILoaderNode, babylonNode: TransformNode): void {
+        private static _LoadTransform(node: _ILoaderNode, babylonNode: TransformNode): void {
             let position = Vector3.Zero();
             let position = Vector3.Zero();
             let rotation = Quaternion.Identity();
             let rotation = Quaternion.Identity();
             let scaling = Vector3.One();
             let scaling = Vector3.One();
@@ -759,7 +757,7 @@ module BABYLON.GLTF2 {
             babylonNode.scaling = scaling;
             babylonNode.scaling = scaling;
         }
         }
 
 
-        private _loadSkinAsync(context: string, node: ILoaderNode, mesh: ILoaderMesh, skin: ILoaderSkin): Promise<void> {
+        private _loadSkinAsync(context: string, node: _ILoaderNode, mesh: _ILoaderMesh, skin: _ILoaderSkin): Promise<void> {
             const assignSkeleton = (skeleton: Skeleton) => {
             const assignSkeleton = (skeleton: Skeleton) => {
                 this._forEachPrimitive(node, babylonMesh => {
                 this._forEachPrimitive(node, babylonMesh => {
                     babylonMesh.skeleton = skeleton;
                     babylonMesh.skeleton = skeleton;
@@ -790,7 +788,7 @@ module BABYLON.GLTF2 {
             }));
             }));
         }
         }
 
 
-        private _loadBones(context: string, skin: ILoaderSkin): void {
+        private _loadBones(context: string, skin: _ILoaderSkin): void {
             const babylonBones: { [index: number]: Bone } = {};
             const babylonBones: { [index: number]: Bone } = {};
             for (const index of skin.joints) {
             for (const index of skin.joints) {
                 const node = GLTFLoader._GetProperty(`${context}/joints/${index}`, this._gltf.nodes, index);
                 const node = GLTFLoader._GetProperty(`${context}/joints/${index}`, this._gltf.nodes, index);
@@ -798,7 +796,7 @@ module BABYLON.GLTF2 {
             }
             }
         }
         }
 
 
-        private _loadBone(node: ILoaderNode, skin: ILoaderSkin, babylonBones: { [index: number]: Bone }): Bone {
+        private _loadBone(node: _ILoaderNode, skin: _ILoaderSkin, babylonBones: { [index: number]: Bone }): Bone {
             let babylonBone = babylonBones[node._index];
             let babylonBone = babylonBones[node._index];
             if (babylonBone) {
             if (babylonBone) {
                 return babylonBone;
                 return babylonBone;
@@ -820,15 +818,13 @@ module BABYLON.GLTF2 {
             return babylonBone;
             return babylonBone;
         }
         }
 
 
-        private _loadSkinInverseBindMatricesDataAsync(context: string, skin: ILoaderSkin): Promise<Nullable<Float32Array>> {
+        private _loadSkinInverseBindMatricesDataAsync(context: string, skin: _ILoaderSkin): Promise<Nullable<Float32Array>> {
             if (skin.inverseBindMatrices == undefined) {
             if (skin.inverseBindMatrices == undefined) {
                 return Promise.resolve(null);
                 return Promise.resolve(null);
             }
             }
 
 
             const accessor = GLTFLoader._GetProperty(`${context}/inverseBindMatrices`, this._gltf.accessors, skin.inverseBindMatrices);
             const accessor = GLTFLoader._GetProperty(`${context}/inverseBindMatrices`, this._gltf.accessors, skin.inverseBindMatrices);
-            return this._loadAccessorAsync(`#/accessors/${accessor._index}`, accessor).then(data => {
-                return data as Float32Array;
-            });
+            return this._loadFloatAccessorAsync(`#/accessors/${accessor._index}`, accessor);
         }
         }
 
 
         private _updateBoneMatrices(babylonSkeleton: Skeleton, inverseBindMatricesData: Nullable<Float32Array>): void {
         private _updateBoneMatrices(babylonSkeleton: Skeleton, inverseBindMatricesData: Nullable<Float32Array>): void {
@@ -850,7 +846,7 @@ module BABYLON.GLTF2 {
             }
             }
         }
         }
 
 
-        private _getNodeMatrix(node: ILoaderNode): Matrix {
+        private _getNodeMatrix(node: _ILoaderNode): Matrix {
             return node.matrix ?
             return node.matrix ?
                 Matrix.FromArray(node.matrix) :
                 Matrix.FromArray(node.matrix) :
                 Matrix.Compose(
                 Matrix.Compose(
@@ -859,6 +855,45 @@ module BABYLON.GLTF2 {
                     node.translation ? Vector3.FromArray(node.translation) : Vector3.Zero());
                     node.translation ? Vector3.FromArray(node.translation) : Vector3.Zero());
         }
         }
 
 
+        private _loadCamera(context: string, camera: _ILoaderCamera, babylonMesh: Mesh): void {
+            const babylonCamera = new FreeCamera(camera.name || `camera${camera._index}`, Vector3.Zero(), this._babylonScene, false);
+            babylonCamera.parent = babylonMesh;
+            babylonCamera.rotation = new Vector3(0, Math.PI, 0);
+
+            switch (camera.type) {
+                case CameraType.PERSPECTIVE: {
+                    const perspective = camera.perspective;
+                    if (!perspective) {
+                        throw new Error(`${context}: Camera perspective properties are missing`);
+                    }
+
+                    babylonCamera.fov = perspective.yfov;
+                    babylonCamera.minZ = perspective.znear;
+                    babylonCamera.maxZ = perspective.zfar || Number.MAX_VALUE;
+                    break;
+                }
+                case CameraType.ORTHOGRAPHIC: {
+                    if (!camera.orthographic) {
+                        throw new Error(`${context}: Camera orthographic properties are missing`);
+                    }
+
+                    babylonCamera.mode = Camera.ORTHOGRAPHIC_CAMERA;
+                    babylonCamera.orthoLeft = -camera.orthographic.xmag;
+                    babylonCamera.orthoRight = camera.orthographic.xmag;
+                    babylonCamera.orthoBottom = -camera.orthographic.ymag;
+                    babylonCamera.orthoTop = camera.orthographic.ymag;
+                    babylonCamera.minZ = camera.orthographic.znear;
+                    babylonCamera.maxZ = camera.orthographic.zfar;
+                    break;
+                }
+                default: {
+                    throw new Error(`${context}: Invalid camera type (${camera.type})`);
+                }
+            }
+
+            this.onCameraLoadedObservable.notifyObservers(babylonCamera);
+        }
+
         private _loadAnimationsAsync(): Promise<void> {
         private _loadAnimationsAsync(): Promise<void> {
             const animations = this._gltf.animations;
             const animations = this._gltf.animations;
             if (!animations) {
             if (!animations) {
@@ -875,14 +910,14 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        private _loadAnimationAsync(context: string, animation: ILoaderAnimation): Promise<void> {
+        private _loadAnimationAsync(context: string, animation: _ILoaderAnimation): Promise<void> {
             const babylonAnimationGroup = new AnimationGroup(animation.name || `animation${animation._index}`, this._babylonScene);
             const babylonAnimationGroup = new AnimationGroup(animation.name || `animation${animation._index}`, this._babylonScene);
             animation._babylonAnimationGroup = babylonAnimationGroup;
             animation._babylonAnimationGroup = babylonAnimationGroup;
 
 
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
-            ArrayItem.Assign(animation.channels);
-            ArrayItem.Assign(animation.samplers);
+            _ArrayItem.Assign(animation.channels);
+            _ArrayItem.Assign(animation.samplers);
 
 
             for (const channel of animation.channels) {
             for (const channel of animation.channels) {
                 promises.push(this._loadAnimationChannelAsync(`${context}/channels/${channel._index}`, context, animation, channel, babylonAnimationGroup));
                 promises.push(this._loadAnimationChannelAsync(`${context}/channels/${channel._index}`, context, animation, channel, babylonAnimationGroup));
@@ -893,9 +928,12 @@ module BABYLON.GLTF2 {
             });
             });
         }
         }
 
 
-        private _loadAnimationChannelAsync(context: string, animationContext: string, animation: ILoaderAnimation, channel: ILoaderAnimationChannel, babylonAnimationGroup: AnimationGroup): Promise<void> {
+        private _loadAnimationChannelAsync(context: string, animationContext: string, animation: _ILoaderAnimation, channel: _ILoaderAnimationChannel, babylonAnimationGroup: AnimationGroup): Promise<void> {
             const targetNode = GLTFLoader._GetProperty(`${context}/target/node`, this._gltf.nodes, channel.target.node);
             const targetNode = GLTFLoader._GetProperty(`${context}/target/node`, this._gltf.nodes, channel.target.node);
-            if (!targetNode._babylonMesh) {
+
+            // Ignore animations that have no animation targets.
+            if ((channel.target.path === AnimationChannelTargetPath.WEIGHTS && !targetNode._numMorphTargets) ||
+                (channel.target.path !== AnimationChannelTargetPath.WEIGHTS && !targetNode._babylonAnimationTargets)) {
                 return Promise.resolve();
                 return Promise.resolve();
             }
             }
 
 
@@ -1044,7 +1082,7 @@ module BABYLON.GLTF2 {
             });
             });
         }
         }
 
 
-        private _loadAnimationSamplerAsync(context: string, sampler: ILoaderAnimationSampler): Promise<ILoaderAnimationSamplerData> {
+        private _loadAnimationSamplerAsync(context: string, sampler: _ILoaderAnimationSampler): Promise<_ILoaderAnimationSamplerData> {
             if (sampler._data) {
             if (sampler._data) {
                 return sampler._data;
                 return sampler._data;
             }
             }
@@ -1061,31 +1099,24 @@ module BABYLON.GLTF2 {
                 }
                 }
             }
             }
 
 
-            let inputData: Nullable<Float32Array>;
-            let outputData: Nullable<Float32Array>;
-
             const inputAccessor = GLTFLoader._GetProperty(`${context}/input`, this._gltf.accessors, sampler.input);
             const inputAccessor = GLTFLoader._GetProperty(`${context}/input`, this._gltf.accessors, sampler.input);
             const outputAccessor = GLTFLoader._GetProperty(`${context}/output`, this._gltf.accessors, sampler.output);
             const outputAccessor = GLTFLoader._GetProperty(`${context}/output`, this._gltf.accessors, sampler.output);
 
 
             sampler._data = Promise.all([
             sampler._data = Promise.all([
-                this._loadAccessorAsync(`#/accessors/${inputAccessor._index}`, inputAccessor).then(data => {
-                    inputData = data as Float32Array;
-                }),
-                this._loadAccessorAsync(`#/accessors/${outputAccessor._index}`, outputAccessor).then(data => {
-                    outputData = data as Float32Array;
-                })
-            ]).then(() => {
+                this._loadFloatAccessorAsync(`#/accessors/${inputAccessor._index}`, inputAccessor),
+                this._loadFloatAccessorAsync(`#/accessors/${outputAccessor._index}`, outputAccessor)
+            ]).then(([inputData, outputData]) => {
                 return {
                 return {
-                    input: inputData!,
+                    input: inputData,
                     interpolation: interpolation,
                     interpolation: interpolation,
-                    output: outputData!,
+                    output: outputData,
                 };
                 };
             });
             });
 
 
             return sampler._data;
             return sampler._data;
         }
         }
 
 
-        private _loadBufferAsync(context: string, buffer: ILoaderBuffer): Promise<ArrayBufferView> {
+        private _loadBufferAsync(context: string, buffer: _ILoaderBuffer): Promise<ArrayBufferView> {
             if (buffer._data) {
             if (buffer._data) {
                 return buffer._data;
                 return buffer._data;
             }
             }
@@ -1099,16 +1130,14 @@ module BABYLON.GLTF2 {
             return buffer._data;
             return buffer._data;
         }
         }
 
 
-        /**
-        * @ignore
-        */
-        public _loadBufferViewAsync(context: string, bufferView: ILoaderBufferView): Promise<ArrayBufferView> {
+        /** @hidden */
+        public _loadBufferViewAsync(context: string, bufferView: _ILoaderBufferView): Promise<ArrayBufferView> {
             if (bufferView._data) {
             if (bufferView._data) {
                 return bufferView._data;
                 return bufferView._data;
             }
             }
 
 
-            const buffer = GLTFLoader._GetProperty(context + "/buffer", this._gltf.buffers, bufferView.buffer);
-            bufferView._data = this._loadBufferAsync("#/buffers/" + buffer._index, buffer).then(data => {
+            const buffer = GLTFLoader._GetProperty(`${context}/buffer`, this._gltf.buffers, bufferView.buffer);
+            bufferView._data = this._loadBufferAsync(`#/buffers/${buffer._index}`, buffer).then(data => {
                 try {
                 try {
                     return new Uint8Array(data.buffer, data.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
                     return new Uint8Array(data.buffer, data.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
                 }
                 }
@@ -1120,58 +1149,83 @@ module BABYLON.GLTF2 {
             return bufferView._data;
             return bufferView._data;
         }
         }
 
 
-        private _loadAccessorAsync(context: string, accessor: ILoaderAccessor): Promise<ArrayBufferView> {
-            if (accessor.sparse) {
-                throw new Error(`${context}: Sparse accessors are not currently supported`);
+        private _loadIndicesAccessorAsync(context: string, accessor: _ILoaderAccessor): Promise<IndicesArray> {
+            if (accessor.type !== AccessorType.SCALAR) {
+                throw new Error(`${context}: Invalid type ${accessor.type}`);
+            }
+
+            if (accessor.componentType !== AccessorComponentType.UNSIGNED_BYTE &&
+                accessor.componentType !== AccessorComponentType.UNSIGNED_SHORT &&
+                accessor.componentType !== AccessorComponentType.UNSIGNED_INT) {
+                throw new Error(`${context}: Invalid component type ${accessor.componentType}`);
             }
             }
 
 
             if (accessor._data) {
             if (accessor._data) {
-                return accessor._data;
+                return accessor._data as Promise<IndicesArray>;
             }
             }
 
 
-            const bufferView = GLTFLoader._GetProperty(context + "/bufferView", this._gltf.bufferViews, accessor.bufferView);
-            accessor._data = this._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView).then(data => {
-                const buffer = data.buffer;
-                const byteOffset = data.byteOffset + (accessor.byteOffset || 0);
-                const length = GLTFLoader._GetNumComponents(context, accessor.type) * accessor.count;
+            const bufferView = GLTFLoader._GetProperty(`${context}/bufferView`, this._gltf.bufferViews, accessor.bufferView);
+            accessor._data = this._loadBufferViewAsync(`#/bufferViews/${bufferView._index}`, bufferView).then(data => {
+                return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count);
+            });
 
 
-                try {
-                    switch (accessor.componentType) {
-                        case AccessorComponentType.BYTE: {
-                            return new Int8Array(buffer, byteOffset, length);
-                        }
-                        case AccessorComponentType.UNSIGNED_BYTE: {
-                            return new Uint8Array(buffer, byteOffset, length);
-                        }
-                        case AccessorComponentType.SHORT: {
-                            return new Int16Array(buffer, byteOffset, length);
-                        }
-                        case AccessorComponentType.UNSIGNED_SHORT: {
-                            return new Uint16Array(buffer, byteOffset, length);
-                        }
-                        case AccessorComponentType.UNSIGNED_INT: {
-                            return new Uint32Array(buffer, byteOffset, length);
-                        }
-                        case AccessorComponentType.FLOAT: {
-                            return new Float32Array(buffer, byteOffset, length);
-                        }
-                        default: {
-                            throw new Error(`${context}: Invalid accessor component type ${accessor.componentType}`);
+            return accessor._data as Promise<IndicesArray>;
+        }
+
+        private _loadFloatAccessorAsync(context: string, accessor: _ILoaderAccessor): Promise<Float32Array> {
+            // TODO: support normalized and stride
+
+            if (accessor.componentType !== AccessorComponentType.FLOAT) {
+                throw new Error(`Invalid component type ${accessor.componentType}`);
+            }
+
+            if (accessor._data) {
+                return accessor._data as Promise<Float32Array>;
+            }
+
+            const numComponents = GLTFLoader._GetNumComponents(context, accessor.type);
+            const length = numComponents * accessor.count;
+
+            if (accessor.bufferView == undefined) {
+                accessor._data = Promise.resolve(new Float32Array(length));
+            }
+            else {
+                const bufferView = GLTFLoader._GetProperty(`${context}/bufferView`, this._gltf.bufferViews, accessor.bufferView);
+                accessor._data = this._loadBufferViewAsync(`#/bufferViews/${bufferView._index}`, bufferView).then(data => {
+                    return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length);
+                });
+            }
+
+            if (accessor.sparse) {
+                const sparse = accessor.sparse;
+                accessor._data = accessor._data.then((data: Float32Array) => {
+                    const indicesBufferView = GLTFLoader._GetProperty(`${context}/sparse/indices/bufferView`, this._gltf.bufferViews, sparse.indices.bufferView);
+                    const valuesBufferView = GLTFLoader._GetProperty(`${context}/sparse/values/bufferView`, this._gltf.bufferViews, sparse.values.bufferView);
+                    return Promise.all([
+                        this._loadBufferViewAsync(`#/bufferViews/${indicesBufferView._index}`, indicesBufferView),
+                        this._loadBufferViewAsync(`#/bufferViews/${valuesBufferView._index}`, valuesBufferView)
+                    ]).then(([indicesData, valuesData]) => {
+                        const indices = GLTFLoader._GetTypedArray(`${context}/sparse/indices`, sparse.indices.componentType, indicesData, sparse.indices.byteOffset, sparse.count) as IndicesArray;
+                        const values = GLTFLoader._GetTypedArray(`${context}/sparse/values`, accessor.componentType, valuesData, sparse.values.byteOffset, numComponents * sparse.count) as Float32Array;
+
+                        let valuesIndex = 0;
+                        for (let indicesIndex = 0; indicesIndex < indices.length; indicesIndex++) {
+                            let dataIndex = indices[indicesIndex] * numComponents;
+                            for (let componentIndex = 0; componentIndex < numComponents; componentIndex++) {
+                                data[dataIndex++] = values[valuesIndex++];
+                            }
                         }
                         }
-                    }
-                }
-                catch (e) {
-                    throw new Error(`${context}: ${e}`);
-                }
-            });
 
 
-            return accessor._data;
+                        return data;
+                    });
+                });
+            }
+
+            return accessor._data as Promise<Float32Array>;
         }
         }
 
 
-        /**
-        * @ignore
-        */
-        public _loadVertexBufferViewAsync(context: string, bufferView: ILoaderBufferView, kind: string): Promise<Buffer> {
+        /** @hidden */
+        public _loadVertexBufferViewAsync(context: string, bufferView: _ILoaderBufferView, kind: string): Promise<Buffer> {
             if (bufferView._babylonBuffer) {
             if (bufferView._babylonBuffer) {
                 return bufferView._babylonBuffer;
                 return bufferView._babylonBuffer;
             }
             }
@@ -1183,21 +1237,24 @@ module BABYLON.GLTF2 {
             return bufferView._babylonBuffer;
             return bufferView._babylonBuffer;
         }
         }
 
 
-        private _loadVertexAccessorAsync(context: string, accessor: ILoaderAccessor, kind: string): Promise<VertexBuffer> {
-            if (accessor.sparse) {
-                throw new Error(`${context}: Sparse accessors are not currently supported`);
-            }
-
+        private _loadVertexAccessorAsync(context: string, accessor: _ILoaderAccessor, kind: string): Promise<VertexBuffer> {
             if (accessor._babylonVertexBuffer) {
             if (accessor._babylonVertexBuffer) {
                 return accessor._babylonVertexBuffer;
                 return accessor._babylonVertexBuffer;
             }
             }
 
 
-            const bufferView = GLTFLoader._GetProperty(context + "/bufferView", this._gltf.bufferViews, accessor.bufferView);
-            accessor._babylonVertexBuffer = this._loadVertexBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView, kind).then(buffer => {
-                const size = GLTFLoader._GetNumComponents(context, accessor.type);
-                return new VertexBuffer(this._babylonScene.getEngine(), buffer, kind, false, false, bufferView.byteStride,
-                    false, accessor.byteOffset, size, accessor.componentType, accessor.normalized, true);
-            });
+            if (accessor.sparse) {
+                accessor._babylonVertexBuffer = this._loadFloatAccessorAsync(context, accessor).then(data => {
+                    return new VertexBuffer(this._babylonScene.getEngine(), data, kind, false);
+                });
+            }
+            else {
+                const bufferView = GLTFLoader._GetProperty(context + "/bufferView", this._gltf.bufferViews, accessor.bufferView);
+                accessor._babylonVertexBuffer = this._loadVertexBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView, kind).then(buffer => {
+                    const size = GLTFLoader._GetNumComponents(context, accessor.type);
+                    return new VertexBuffer(this._babylonScene.getEngine(), buffer, kind, false, false, bufferView.byteStride,
+                        false, accessor.byteOffset, size, accessor.componentType, accessor.normalized, true);
+                });
+            }
 
 
             return accessor._babylonVertexBuffer;
             return accessor._babylonVertexBuffer;
         }
         }
@@ -1215,7 +1272,7 @@ module BABYLON.GLTF2 {
             return babylonMaterial;
             return babylonMaterial;
         }
         }
 
 
-        private _loadMaterialMetallicRoughnessPropertiesAsync(context: string, material: ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
+        private _loadMaterialMetallicRoughnessPropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
             // Ensure metallic workflow
             // Ensure metallic workflow
@@ -1257,10 +1314,8 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        /**
-        * @ignore
-        */
-        public _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void> {
+        /** @hidden */
+        public _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void> {
             const promise = GLTFLoaderExtension._LoadMaterialAsync(this, context, material, babylonMesh, babylonDrawMode, assign);
             const promise = GLTFLoaderExtension._LoadMaterialAsync(this, context, material, babylonMesh, babylonDrawMode, assign);
             if (promise) {
             if (promise) {
                 return promise;
                 return promise;
@@ -1294,20 +1349,16 @@ module BABYLON.GLTF2 {
             return babylonData.loaded;
             return babylonData.loaded;
         }
         }
 
 
-        /**
-        * @ignore
-        */
-        public _createMaterial<T extends Material>(type: MaterialConstructor<T>, name: string, drawMode: number): T {
+        /** @hidden */
+        public _createMaterial<T extends Material>(type: _MaterialConstructor<T>, name: string, drawMode: number): T {
             const babylonMaterial = new type(name, this._babylonScene);
             const babylonMaterial = new type(name, this._babylonScene);
             babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
             babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
             babylonMaterial.fillMode = drawMode;
             babylonMaterial.fillMode = drawMode;
             return babylonMaterial;
             return babylonMaterial;
         }
         }
 
 
-        /**
-        * @ignore
-        */
-        public _loadMaterialBasePropertiesAsync(context: string, material: ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
+        /** @hidden */
+        public _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
             babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0);
             babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0);
@@ -1348,10 +1399,8 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        /**
-        * @ignore
-        */
-        public _loadMaterialAlphaProperties(context: string, material: ILoaderMaterial, babylonMaterial: PBRMaterial): void {
+        /** @hidden */
+        public _loadMaterialAlphaProperties(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): void {
             const alphaMode = material.alphaMode || MaterialAlphaMode.OPAQUE;
             const alphaMode = material.alphaMode || MaterialAlphaMode.OPAQUE;
             switch (alphaMode) {
             switch (alphaMode) {
                 case MaterialAlphaMode.OPAQUE: {
                 case MaterialAlphaMode.OPAQUE: {
@@ -1380,9 +1429,7 @@ module BABYLON.GLTF2 {
             }
             }
         }
         }
 
 
-        /**
-        * @ignore
-        */
+        /** @hidden */
         public _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Promise<void> {
         public _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Promise<void> {
             const texture = GLTFLoader._GetProperty(`${context}/index`, this._gltf.textures, textureInfo.index);
             const texture = GLTFLoader._GetProperty(`${context}/index`, this._gltf.textures, textureInfo.index);
             context = `#/textures/${textureInfo.index}`;
             context = `#/textures/${textureInfo.index}`;
@@ -1420,7 +1467,7 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        private _loadSampler(context: string, sampler: ILoaderSampler): ILoaderSamplerData {
+        private _loadSampler(context: string, sampler: _ILoaderSampler): _ILoaderSamplerData {
             if (!sampler._data) {
             if (!sampler._data) {
                 sampler._data = {
                 sampler._data = {
                     noMipMaps: (sampler.minFilter === TextureMinFilter.NEAREST || sampler.minFilter === TextureMinFilter.LINEAR),
                     noMipMaps: (sampler.minFilter === TextureMinFilter.NEAREST || sampler.minFilter === TextureMinFilter.LINEAR),
@@ -1433,7 +1480,7 @@ module BABYLON.GLTF2 {
             return sampler._data;
             return sampler._data;
         }
         }
 
 
-        private _loadImageAsync(context: string, image: ILoaderImage): Promise<string> {
+        private _loadImageAsync(context: string, image: _ILoaderImage): Promise<string> {
             if (image._objectURL) {
             if (image._objectURL) {
                 return image._objectURL;
                 return image._objectURL;
             }
             }
@@ -1454,9 +1501,7 @@ module BABYLON.GLTF2 {
             return image._objectURL;
             return image._objectURL;
         }
         }
 
 
-        /**
-        * @ignore
-        */
+        /** @hidden */
         public _loadUriAsync(context: string, uri: string): Promise<ArrayBufferView> {
         public _loadUriAsync(context: string, uri: string): Promise<ArrayBufferView> {
             const promise = GLTFLoaderExtension._LoadUriAsync(this, context, uri);
             const promise = GLTFLoaderExtension._LoadUriAsync(this, context, uri);
             if (promise) {
             if (promise) {
@@ -1521,9 +1566,7 @@ module BABYLON.GLTF2 {
             this._progressCallback(new SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             this._progressCallback(new SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
         }
         }
 
 
-        /**
-        * @ignore
-        */
+        /** @hidden */
         public static _GetProperty<T>(context: string, array: ArrayLike<T> | undefined, index: number | undefined): T {
         public static _GetProperty<T>(context: string, array: ArrayLike<T> | undefined, index: number | undefined): T {
             if (!array || index == undefined || !array[index]) {
             if (!array || index == undefined || !array[index]) {
                 throw new Error(`${context}: Failed to find index (${index})`);
                 throw new Error(`${context}: Failed to find index (${index})`);
@@ -1583,6 +1626,26 @@ module BABYLON.GLTF2 {
             }
             }
         }
         }
 
 
+        private static _GetTypedArray(context: string, componentType: AccessorComponentType, bufferView: ArrayBufferView, byteOffset: number | undefined, length: number): ArrayBufferView {
+            const buffer = bufferView.buffer;
+            byteOffset = bufferView.byteOffset + (byteOffset || 0);
+
+            try {
+                switch (componentType) {
+                    case AccessorComponentType.BYTE: return new Int8Array(buffer, byteOffset, length);
+                    case AccessorComponentType.UNSIGNED_BYTE: return new Uint8Array(buffer, byteOffset, length);
+                    case AccessorComponentType.SHORT: return new Int16Array(buffer, byteOffset, length);
+                    case AccessorComponentType.UNSIGNED_SHORT: return new Uint16Array(buffer, byteOffset, length);
+                    case AccessorComponentType.UNSIGNED_INT: return new Uint32Array(buffer, byteOffset, length);
+                    case AccessorComponentType.FLOAT: return new Float32Array(buffer, byteOffset, length);
+                    default: throw new Error(`Invalid component type ${componentType}`);
+                }
+            }
+            catch (e) {
+                throw new Error(`${context}: ${e}`);
+            }
+        }
+
         private static _GetNumComponents(context: string, type: string): number {
         private static _GetNumComponents(context: string, type: string): number {
             switch (type) {
             switch (type) {
                 case "SCALAR": return 1;
                 case "SCALAR": return 1;
@@ -1694,11 +1757,10 @@ module BABYLON.GLTF2 {
             this.onMeshLoadedObservable.clear();
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
+            this.onCameraLoadedObservable.clear();
         }
         }
 
 
-        /**
-        * @ignore
-        */
+        /** @hidden */
         public _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>) {
         public _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>) {
             for (const name of GLTFLoader._Names) {
             for (const name of GLTFLoader._Names) {
                 const extension = this._extensions[name];
                 const extension = this._extensions[name];

+ 15 - 9
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -2,7 +2,7 @@
 
 
 module BABYLON.GLTF2 {
 module BABYLON.GLTF2 {
     /**
     /**
-     * Abstract class that can be implemented to extend existing gltf loader behavior.
+     * Abstract class that can be implemented to extend existing glTF loader behavior.
      */
      */
     export abstract class GLTFLoaderExtension implements IGLTFLoaderExtension, IDisposable {
     export abstract class GLTFLoaderExtension implements IGLTFLoaderExtension, IDisposable {
         public enabled = true;
         public enabled = true;
@@ -21,16 +21,16 @@ module BABYLON.GLTF2 {
         // #region Overridable Methods
         // #region Overridable Methods
 
 
         /** Override this method to modify the default behavior for loading scenes. */
         /** Override this method to modify the default behavior for loading scenes. */
-        protected _loadSceneAsync(context: string, node: ILoaderScene): Nullable<Promise<void>> { return null; }
+        protected _loadSceneAsync(context: string, node: _ILoaderScene): Nullable<Promise<void>> { return null; }
 
 
         /** Override this method to modify the default behavior for loading nodes. */
         /** Override this method to modify the default behavior for loading nodes. */
-        protected _loadNodeAsync(context: string, node: ILoaderNode): Nullable<Promise<void>> { return null; }
+        protected _loadNodeAsync(context: string, node: _ILoaderNode): Nullable<Promise<void>> { return null; }
 
 
         /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
         /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
-        protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> { return null; }
+        protected _loadVertexDataAsync(context: string, primitive: _ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> { return null; }
 
 
         /** Override this method to modify the default behavior for loading materials. */
         /** Override this method to modify the default behavior for loading materials. */
-        protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> { return null; }
+        protected _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> { return null; }
 
 
         /** Override this method to modify the default behavior for loading uris. */
         /** Override this method to modify the default behavior for loading uris. */
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>> { return null; }
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>> { return null; }
@@ -63,22 +63,22 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /** Helper method called by the loader to allow extensions to override loading scenes. */
         /** Helper method called by the loader to allow extensions to override loading scenes. */
-        public static _LoadSceneAsync(loader: GLTFLoader, context: string, scene: ILoaderScene): Nullable<Promise<void>> {
+        public static _LoadSceneAsync(loader: GLTFLoader, context: string, scene: _ILoaderScene): Nullable<Promise<void>> {
             return loader._applyExtensions(extension => extension._loadSceneAsync(context, scene));
             return loader._applyExtensions(extension => extension._loadSceneAsync(context, scene));
         }
         }
 
 
         /** Helper method called by the loader to allow extensions to override loading nodes. */
         /** Helper method called by the loader to allow extensions to override loading nodes. */
-        public static _LoadNodeAsync(loader: GLTFLoader, context: string, node: ILoaderNode): Nullable<Promise<void>> {
+        public static _LoadNodeAsync(loader: GLTFLoader, context: string, node: _ILoaderNode): Nullable<Promise<void>> {
             return loader._applyExtensions(extension => extension._loadNodeAsync(context, node));
             return loader._applyExtensions(extension => extension._loadNodeAsync(context, node));
         }
         }
 
 
         /** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
         /** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
-        public static _LoadVertexDataAsync(loader: GLTFLoader, context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> {
+        public static _LoadVertexDataAsync(loader: GLTFLoader, context: string, primitive: _ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> {
             return loader._applyExtensions(extension => extension._loadVertexDataAsync(context, primitive, babylonMesh));
             return loader._applyExtensions(extension => extension._loadVertexDataAsync(context, primitive, babylonMesh));
         }
         }
 
 
         /** Helper method called by the loader to allow extensions to override loading materials. */
         /** Helper method called by the loader to allow extensions to override loading materials. */
-        public static _LoadMaterialAsync(loader: GLTFLoader, context: string, material: ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+        public static _LoadMaterialAsync(loader: GLTFLoader, context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
             return loader._applyExtensions(extension => extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign));
             return loader._applyExtensions(extension => extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign));
         }
         }
 
 
@@ -87,4 +87,10 @@ module BABYLON.GLTF2 {
             return loader._applyExtensions(extension => extension._loadUriAsync(context, uri));
             return loader._applyExtensions(extension => extension._loadUriAsync(context, uri));
         }
         }
     }
     }
+}
+
+/**
+ * Defines the module of the glTF 2.0 loader extensions.
+ */
+module BABYLON.GLTF2.Extensions {
 }
 }

+ 59 - 100
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -1,82 +1,59 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../dist/babylon.glTF2Interface.d.ts"/>
 /// <reference path="../../../../dist/babylon.glTF2Interface.d.ts"/>
 
 
-/**
- * GLTF2 module for babylon
- */
 module BABYLON.GLTF2 {
 module BABYLON.GLTF2 {
-    /**
-     * Interface to access data and vertex buffer associated with a file
-     */
-    export interface ILoaderAccessor extends IAccessor, IArrayItem {
+    /** @hidden */
+    export interface _ILoaderAccessor extends IAccessor, _IArrayItem {
         _data?: Promise<ArrayBufferView>;
         _data?: Promise<ArrayBufferView>;
         _babylonVertexBuffer?: Promise<VertexBuffer>;
         _babylonVertexBuffer?: Promise<VertexBuffer>;
     }
     }
 
 
-    /**
-     * Loader's animation channel
-     */
-    export interface ILoaderAnimationChannel extends IAnimationChannel, IArrayItem {
+    /** @hidden */
+    export interface _ILoaderAnimationChannel extends IAnimationChannel, _IArrayItem {
     }
     }
 
 
-    /**
-     * Container for animation keyframe data
-     */
-    export interface ILoaderAnimationSamplerData {
+    /** @hidden */
+    export interface _ILoaderAnimationSamplerData {
         input: Float32Array;
         input: Float32Array;
         interpolation: AnimationSamplerInterpolation;
         interpolation: AnimationSamplerInterpolation;
         output: Float32Array;
         output: Float32Array;
     }
     }
 
 
-    /**
-     * Keyframe data
-     */
-    export interface ILoaderAnimationSampler extends IAnimationSampler, IArrayItem {
-        _data: Promise<ILoaderAnimationSamplerData>;
+    /** @hidden */
+    export interface _ILoaderAnimationSampler extends IAnimationSampler, _IArrayItem {
+        _data: Promise<_ILoaderAnimationSamplerData>;
     }
     }
 
 
-    /**
-     * Loader animation
-     */
-    export interface ILoaderAnimation extends IAnimation, IArrayItem {
-        channels: ILoaderAnimationChannel[];
-        samplers: ILoaderAnimationSampler[];
+    /** @hidden */
+    export interface _ILoaderAnimation extends IAnimation, _IArrayItem {
+        channels: _ILoaderAnimationChannel[];
+        samplers: _ILoaderAnimationSampler[];
 
 
         _babylonAnimationGroup?: AnimationGroup;
         _babylonAnimationGroup?: AnimationGroup;
     }
     }
 
 
-    /**
-     * Loader buffer
-     */
-    export interface ILoaderBuffer extends IBuffer, IArrayItem {
+    /** @hidden */
+    export interface _ILoaderBuffer extends IBuffer, _IArrayItem {
         _data?: Promise<ArrayBufferView>;
         _data?: Promise<ArrayBufferView>;
     }
     }
 
 
-    /**
-     * Loader's buffer data
-     */
-    export interface ILoaderBufferView extends IBufferView, IArrayItem {
+    /** @hidden */
+    export interface _ILoaderBufferView extends IBufferView, _IArrayItem {
         _data?: Promise<ArrayBufferView>;
         _data?: Promise<ArrayBufferView>;
         _babylonBuffer?: Promise<Buffer>;
         _babylonBuffer?: Promise<Buffer>;
     }
     }
 
 
-    /**
-     * Loader's loaded camera data
-     */
-    export interface ILoaderCamera extends ICamera, IArrayItem {
+    /** @hidden */
+    export interface _ILoaderCamera extends ICamera, _IArrayItem {
     }
     }
 
 
-    /**
-     * Loaded image specified by url
-     */
-    export interface ILoaderImage extends IImage, IArrayItem {
+    /** @hidden */
+    export interface _ILoaderImage extends IImage, _IArrayItem {
         _objectURL?: Promise<string>;
         _objectURL?: Promise<string>;
     }
     }
 
 
-    /**
-     * Loaded material data
-     */
-    export interface ILoaderMaterial extends IMaterial, IArrayItem {
+    /** @hidden */
+    export interface _ILoaderMaterial extends IMaterial, _IArrayItem {
         _babylonData?: {
         _babylonData?: {
             [drawMode: number]: {
             [drawMode: number]: {
                 material: Material;
                 material: Material;
@@ -86,83 +63,65 @@ module BABYLON.GLTF2 {
         };
         };
     }
     }
 
 
-    /**
-     * Loader mesh data
-     */
-    export interface ILoaderMesh extends IMesh, IArrayItem {
-        primitives: ILoaderMeshPrimitive[];
+    /** @hidden */
+    export interface _ILoaderMesh extends IMesh, _IArrayItem {
+        primitives: _ILoaderMeshPrimitive[];
     }
     }
 
 
-    /**
-     * Loader mesh data
-     */
-    export interface ILoaderMeshPrimitive extends IMeshPrimitive, IArrayItem {
+    /** @hidden */
+    export interface _ILoaderMeshPrimitive extends IMeshPrimitive, _IArrayItem {
     }
     }
 
 
-    /**
-     * Node for traversing loader data
-     */
-    export interface ILoaderNode extends INode, IArrayItem {
-        _parent: ILoaderNode;
+    /** @hidden */
+    export interface _ILoaderNode extends INode, _IArrayItem {
+        _parent: _ILoaderNode;
         _babylonMesh?: Mesh;
         _babylonMesh?: Mesh;
         _primitiveBabylonMeshes?: Mesh[];
         _primitiveBabylonMeshes?: Mesh[];
         _babylonAnimationTargets?: Node[];
         _babylonAnimationTargets?: Node[];
         _numMorphTargets?: number;
         _numMorphTargets?: number;
     }
     }
 
 
-    /**
-     * Sampler data
-     */
-    export interface ILoaderSamplerData {
+    /** @hidden */
+    export interface _ILoaderSamplerData {
         noMipMaps: boolean;
         noMipMaps: boolean;
         samplingMode: number;
         samplingMode: number;
         wrapU: number;
         wrapU: number;
         wrapV: number;
         wrapV: number;
     }
     }
 
 
-    /**
-     * Sampler data
-     */
-    export interface ILoaderSampler extends ISampler, IArrayItem {
-        _data?: ILoaderSamplerData;
+    /** @hidden */
+    export interface _ILoaderSampler extends ISampler, _IArrayItem {
+        _data?: _ILoaderSamplerData;
     }
     }
 
 
-    /**
-     * Loader's scene
-     */
-    export interface ILoaderScene extends IScene, IArrayItem {
+    /** @hidden */
+    export interface _ILoaderScene extends IScene, _IArrayItem {
     }
     }
 
 
-    /**
-     * Loader's skeleton data
-     */
-    export interface ILoaderSkin extends ISkin, IArrayItem {
+    /** @hidden */
+    export interface _ILoaderSkin extends ISkin, _IArrayItem {
         _babylonSkeleton?: Skeleton;
         _babylonSkeleton?: Skeleton;
         _loaded?: Promise<void>;
         _loaded?: Promise<void>;
     }
     }
 
 
-    /**
-     * Loader's texture
-     */
-    export interface ILoaderTexture extends ITexture, IArrayItem {
-    }
-
-    /**
-     * Loaded GLTF data
-     */
-    export interface ILoaderGLTF extends IGLTF {
-        accessors?: ILoaderAccessor[];
-        animations?: ILoaderAnimation[];
-        buffers?: ILoaderBuffer[];
-        bufferViews?: ILoaderBufferView[];
-        cameras?: ILoaderCamera[];
-        images?: ILoaderImage[];
-        materials?: ILoaderMaterial[];
-        meshes?: ILoaderMesh[];
-        nodes?: ILoaderNode[];
-        samplers?: ILoaderSampler[];
-        scenes?: ILoaderScene[];
-        skins?: ILoaderSkin[];
-        textures?: ILoaderTexture[];
+    /** @hidden */
+    export interface _ILoaderTexture extends ITexture, _IArrayItem {
+    }
+
+    /** @hidden */
+    export interface _ILoaderGLTF extends IGLTF {
+        accessors?: _ILoaderAccessor[];
+        animations?: _ILoaderAnimation[];
+        buffers?: _ILoaderBuffer[];
+        bufferViews?: _ILoaderBufferView[];
+        cameras?: _ILoaderCamera[];
+        images?: _ILoaderImage[];
+        materials?: _ILoaderMaterial[];
+        meshes?: _ILoaderMesh[];
+        nodes?: _ILoaderNode[];
+        samplers?: _ILoaderSampler[];
+        scenes?: _ILoaderScene[];
+        skins?: _ILoaderSkin[];
+        textures?: _ILoaderTexture[];
     }
     }
 }
 }

+ 7 - 6
loaders/src/glTF/2.0/babylon.glTFLoaderUtilities.ts

@@ -1,14 +1,15 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 
 
 module BABYLON.GLTF2 {
 module BABYLON.GLTF2 {
-    /** Array item which contains it's index in an array */
-    export interface IArrayItem {
+    /** @hidden */
+    export interface _IArrayItem {
         _index: number;
         _index: number;
     }
     }
-    /** Array item helper methods */
-    export class ArrayItem {
-        /** Sets the index of each array element to its index in the array */
-        public static Assign(values?: IArrayItem[]): void {
+
+    /** @hidden */
+    export class _ArrayItem {
+        /** @hidden */
+        public static Assign(values?: _IArrayItem[]): void {
             if (values) {
             if (values) {
                 for (let index = 0; index < values.length; index++) {
                 for (let index = 0; index < values.length; index++) {
                     values[index]._index = index;
                     values[index]._index = index;

+ 158 - 99
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -2,8 +2,8 @@
 
 
 module BABYLON {
 module BABYLON {
     /**
     /**
-    * Coordinate system mode that will be used when loading from the gltf file
-    */
+     * Mode that determines the coordinate system to use.
+     */
     export enum GLTFLoaderCoordinateSystemMode {
     export enum GLTFLoaderCoordinateSystemMode {
         /**
         /**
          * Automatically convert the glTF right-handed data to the appropriate system based on the current coordinate system mode of the scene.
          * Automatically convert the glTF right-handed data to the appropriate system based on the current coordinate system mode of the scene.
@@ -17,8 +17,8 @@ module BABYLON {
     }
     }
 
 
     /**
     /**
-    * Animation mode that determines which animations should be started when a file is loaded
-    */
+     * Mode that determines what animations will start.
+     */
     export enum GLTFLoaderAnimationStartMode {
     export enum GLTFLoaderAnimationStartMode {
         /**
         /**
          * No animation will start.
          * No animation will start.
@@ -37,22 +37,23 @@ module BABYLON {
     }
     }
 
 
     /**
     /**
-    * Loaded gltf data
-    */
+     * Interface that contains the data for the glTF asset.
+     */
     export interface IGLTFLoaderData {
     export interface IGLTFLoaderData {
         /**
         /**
-        * Loaded json string converted to an object
-        */
+         * JSON that represents the glTF.
+         */
         json: Object;
         json: Object;
+
         /**
         /**
-        * Loaded ArrayBufferView
-        */
+         * The BIN chunk of a binary glTF
+         */
         bin: Nullable<ArrayBufferView>;
         bin: Nullable<ArrayBufferView>;
     }
     }
 
 
     /**
     /**
-    * Gltf extension interface
-    */
+     * Interface for extending the loader.
+     */
     export interface IGLTFLoaderExtension {
     export interface IGLTFLoaderExtension {
         /**
         /**
          * The name of this extension.
          * The name of this extension.
@@ -60,14 +61,14 @@ module BABYLON {
         readonly name: string;
         readonly name: string;
 
 
         /**
         /**
-         * Whether this extension is enabled.
+         * Defines whether this extension is enabled.
          */
          */
         enabled: boolean;
         enabled: boolean;
     }
     }
 
 
     /**
     /**
-    * Loading state
-    */
+     * Loader state.
+     */
     export enum GLTFLoaderState {
     export enum GLTFLoaderState {
         /**
         /**
          * The asset is loading.
          * The asset is loading.
@@ -86,87 +87,114 @@ module BABYLON {
     }
     }
 
 
     /**
     /**
-    * GLTF loader interface
-    */
+     * Loader interface.
+     */
     export interface IGLTFLoader extends IDisposable {
     export interface IGLTFLoader extends IDisposable {
         /**
         /**
-        * Coordinate system that will be used when loading from the gltf file
-        */
+         * Mode that determines the coordinate system to use.
+         */
         coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
         coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
+
         /**
         /**
-        * Animation mode that determines which animations should be started when a file is loaded
-        */
+         * Mode that determines what animations will start.
+         */
         animationStartMode: GLTFLoaderAnimationStartMode;
         animationStartMode: GLTFLoaderAnimationStartMode;
+
         /**
         /**
-        * If the materials in the file should automatically be compiled
-        */
+         * Defines if the loader should compile materials.
+         */
         compileMaterials: boolean;
         compileMaterials: boolean;
+
         /**
         /**
-        * If a clip plane should be usede when loading meshes in the file
-        */
+         * Defines if the loader should also compile materials with clip planes.
+         */
         useClipPlane: boolean;
         useClipPlane: boolean;
+
         /**
         /**
-        * If shadow generators should automatically be compiled
-        */
+         * Defines if the loader should compile shadow generators.
+         */
         compileShadowGenerators: boolean;
         compileShadowGenerators: boolean;
 
 
         /**
         /**
-        * Observable that fires each time a mesh is loaded
-        */
+         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
+         */
         onMeshLoadedObservable: Observable<AbstractMesh>;
         onMeshLoadedObservable: Observable<AbstractMesh>;
+
         /**
         /**
-        * Observable that fires each time a texture is loaded
-        */
+         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
+         */
         onTextureLoadedObservable: Observable<BaseTexture>;
         onTextureLoadedObservable: Observable<BaseTexture>;
-         /**
-        * Observable that fires each time a material is loaded
-        */
+
+        /**
+         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
+         */
         onMaterialLoadedObservable: Observable<Material>;
         onMaterialLoadedObservable: Observable<Material>;
+
         /**
         /**
-        * Observable that fires when the load has completed
-        */
+         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
+         */
+        onCameraLoadedObservable: Observable<Camera>;
+
+        /**
+         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
+         * For assets with LODs, raised when all of the LODs are complete.
+         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
+         */
         onCompleteObservable: Observable<IGLTFLoader>;
         onCompleteObservable: Observable<IGLTFLoader>;
+
         /**
         /**
-        * Observable that fires when the loader is disposed
-        */
+         * Observable raised after the loader is disposed.
+         */
         onDisposeObservable: Observable<IGLTFLoader>;
         onDisposeObservable: Observable<IGLTFLoader>;
+
         /**
         /**
-        * Observable that fire when an extension is loaded
-        */
+         * Observable raised after a loader extension is created.
+         * Set additional options for a loader extension in this event.
+         */
         onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
 
 
         /**
         /**
-        * Loader state
-        */
+         * Loader state or null if the loader is not active.
+         */
         state: Nullable<GLTFLoaderState>;
         state: Nullable<GLTFLoaderState>;
 
 
         /**
         /**
-        * Imports one or more meshes from a loaded gltf file and adds them to the scene
-        */
+         * Imports meshes from the given data and adds them to the scene.
+         */
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }>;
+
         /**
         /**
-        * Imports all objects from a loaded gltf file and adds them to the scene
-        */
+         * Loads all objects from the given data and adds them to the scene.
+         */
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
     }
     }
-    /** File loader to load gltf files into a babylon scene */
+
+    /**
+     * File loader for loading glTF files into a scene.
+     */
     export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
     export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
-        /** Creates a gltf 1.0 file loader */
+        /**
+         * Factory function that creates a glTF 1.0 loader
+         */
         public static CreateGLTFLoaderV1: () => IGLTFLoader;
         public static CreateGLTFLoaderV1: () => IGLTFLoader;
-        /** Creates a gltf 2.0 file loader */
+
+        /**
+         * Factory function that creates a glTF 2.0 loader
+         */
         public static CreateGLTFLoaderV2: () => IGLTFLoader;
         public static CreateGLTFLoaderV2: () => IGLTFLoader;
 
 
         // #region Common options
         // #region Common options
 
 
         /**
         /**
-         * Raised when the asset has been parsed.
-         * The data.json property stores the glTF JSON.
-         * The data.bin property stores the BIN chunk from a glTF binary or null if the input is not a glTF binary.
+         * Raised when the asset has been parsed
          */
          */
         public onParsedObservable = new Observable<IGLTFLoaderData>();
         public onParsedObservable = new Observable<IGLTFLoaderData>();
 
 
         private _onParsedObserver: Nullable<Observer<IGLTFLoaderData>>;
         private _onParsedObserver: Nullable<Observer<IGLTFLoaderData>>;
-        /** Raised when the asset has been parsed. */
+
+        /**
+         * Raised when the asset has been parsed
+         */
         public set onParsed(callback: (loaderData: IGLTFLoaderData) => void) {
         public set onParsed(callback: (loaderData: IGLTFLoaderData) => void) {
             if (this._onParsedObserver) {
             if (this._onParsedObserver) {
                 this.onParsedObservable.remove(this._onParsedObserver);
                 this.onParsedObservable.remove(this._onParsedObserver);
@@ -177,13 +205,17 @@ module BABYLON {
         // #endregion
         // #endregion
 
 
         // #region V1 options
         // #region V1 options
+
         /**
         /**
-         * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders. Textures always loads asynchronously. For example, the success callback can compute the bounding information of the loaded meshes when incremental loading is disabled. Defaults to true.
+         * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders.
+         * Textures always loads asynchronously. For example, the success callback can compute the bounding information of the loaded meshes when incremental loading is disabled.
+         * Defaults to true.
          */
          */
         public static IncrementalLoading = true;
         public static IncrementalLoading = true;
 
 
         /**
         /**
-         * Set this property to true in order to work with homogeneous coordinates, available with some converters and exporters. Defaults to false. See https://en.wikipedia.org/wiki/Homogeneous_coordinates
+         * Set this property to true in order to work with homogeneous coordinates, available with some converters and exporters.
+         * Defaults to false. See https://en.wikipedia.org/wiki/Homogeneous_coordinates.
          */
          */
         public static HomogeneousCoordinates = false;
         public static HomogeneousCoordinates = false;
 
 
@@ -192,43 +224,39 @@ module BABYLON {
         // #region V2 options
         // #region V2 options
 
 
         /**
         /**
-         * The coordinate system mode (AUTO, FORCE_RIGHT_HANDED). Defaults to AUTO.
-         * - AUTO - Automatically convert the glTF right-handed data to the appropriate system based on the current coordinate system mode of the scene.
-         * - FORCE_RIGHT_HANDED - Sets the useRightHandedSystem flag on the scene.
+         * The coordinate system mode. Defaults to AUTO.
          */
          */
         public coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
         public coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
 
 
         /**
         /**
-        * The animation start mode (NONE, FIRST, ALL). Defaults to FIRST.
-        * - NONE - No animation will start.
-        * - FIRST - The first animation will start.
-        * - ALL - All animations will start.
+        * The animation start mode. Defaults to FIRST.
         */
         */
         public animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
         public animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
 
 
         /**
         /**
-         * Set to true to compile materials before raising the success callback. Defaults to false.
+         * Defines if the loader should compile materials before raising the success callback. Defaults to false.
          */
          */
         public compileMaterials = false;
         public compileMaterials = false;
 
 
         /**
         /**
-         * Set to true to also compile materials with clip planes. Defaults to false.
+         * Defines if the loader should also compile materials with clip planes. Defaults to false.
          */
          */
         public useClipPlane = false;
         public useClipPlane = false;
 
 
         /**
         /**
-         * Set to true to compile shadow generators before raising the success callback. Defaults to false.
+         * Defines if the loader should compile shadow generators before raising the success callback. Defaults to false.
          */
          */
         public compileShadowGenerators = false;
         public compileShadowGenerators = false;
 
 
         /**
         /**
-         * Raised when the loader creates a mesh after parsing the glTF properties of the mesh.
+         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
          */
         public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
         public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
 
 
         private _onMeshLoadedObserver: Nullable<Observer<AbstractMesh>>;
         private _onMeshLoadedObserver: Nullable<Observer<AbstractMesh>>;
+
         /**
         /**
-         * Raised when the loader creates a mesh after parsing the glTF properties of the mesh. (onMeshLoadedObservable is likely desired instead.)
+         * Callback raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
          */
         public set onMeshLoaded(callback: (mesh: AbstractMesh) => void) {
         public set onMeshLoaded(callback: (mesh: AbstractMesh) => void) {
             if (this._onMeshLoadedObserver) {
             if (this._onMeshLoadedObserver) {
@@ -238,13 +266,14 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-         * Raised when the loader creates a texture after parsing the glTF properties of the texture.
+         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
          */
          */
         public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
         public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
 
 
         private _onTextureLoadedObserver: Nullable<Observer<BaseTexture>>;
         private _onTextureLoadedObserver: Nullable<Observer<BaseTexture>>;
+
         /**
         /**
-         * Method called when a texture has been loaded (onTextureLoadedObservable is likely desired instead.)
+         * Callback raised when the loader creates a texture after parsing the glTF properties of the texture.
          */
          */
         public set onTextureLoaded(callback: (texture: BaseTexture) => void) {
         public set onTextureLoaded(callback: (texture: BaseTexture) => void) {
             if (this._onTextureLoadedObserver) {
             if (this._onTextureLoadedObserver) {
@@ -254,13 +283,14 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-         * Raised when the loader creates a material after parsing the glTF properties of the material.
+         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
          */
          */
         public readonly onMaterialLoadedObservable = new Observable<Material>();
         public readonly onMaterialLoadedObservable = new Observable<Material>();
 
 
         private _onMaterialLoadedObserver: Nullable<Observer<Material>>;
         private _onMaterialLoadedObserver: Nullable<Observer<Material>>;
+
         /**
         /**
-         * Method when the loader creates a material after parsing the glTF properties of the material. (onMaterialLoadedObservable is likely desired instead.)
+         * Callback raised when the loader creates a material after parsing the glTF properties of the material.
          */
          */
         public set onMaterialLoaded(callback: (material: Material) => void) {
         public set onMaterialLoaded(callback: (material: Material) => void) {
             if (this._onMaterialLoadedObserver) {
             if (this._onMaterialLoadedObserver) {
@@ -270,15 +300,33 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-         * Raised when the asset is completely loaded, immediately before the loader is disposed.
+         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
+         */
+        public readonly onCameraLoadedObservable = new Observable<Camera>();
+
+        private _onCameraLoadedObserver: Nullable<Observer<Camera>>;
+
+        /**
+         * Callback raised when the loader creates a camera after parsing the glTF properties of the camera.
+         */
+        public set onCameraLoaded(callback: (camera: Camera) => void) {
+            if (this._onCameraLoadedObserver) {
+                this.onCameraLoadedObservable.remove(this._onCameraLoadedObserver);
+            }
+            this._onCameraLoadedObserver = this.onCameraLoadedObservable.add(callback);
+        }
+
+        /**
+         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          */
          */
         public readonly onCompleteObservable = new Observable<GLTFFileLoader>();
         public readonly onCompleteObservable = new Observable<GLTFFileLoader>();
 
 
         private _onCompleteObserver: Nullable<Observer<GLTFFileLoader>>;
         private _onCompleteObserver: Nullable<Observer<GLTFFileLoader>>;
+
         /**
         /**
-         * Raised when the asset is completely loaded, immediately before the loader is disposed. (onCompleteObservable is likely desired instead.)
+         * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
          */
          */
         public set onComplete(callback: () => void) {
         public set onComplete(callback: () => void) {
             if (this._onCompleteObserver) {
             if (this._onCompleteObserver) {
@@ -288,13 +336,14 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-        * Raised after the loader is disposed.
-        */
+         * Observable raised after the loader is disposed.
+         */
         public readonly onDisposeObservable = new Observable<GLTFFileLoader>();
         public readonly onDisposeObservable = new Observable<GLTFFileLoader>();
 
 
         private _onDisposeObserver: Nullable<Observer<GLTFFileLoader>>;
         private _onDisposeObserver: Nullable<Observer<GLTFFileLoader>>;
+
         /**
         /**
-         * Raised after the loader is disposed. (onDisposeObservable is likely desired instead.)
+         * Callback raised after the loader is disposed.
          */
          */
         public set onDispose(callback: () => void) {
         public set onDispose(callback: () => void) {
             if (this._onDisposeObserver) {
             if (this._onDisposeObserver) {
@@ -304,14 +353,15 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-         * Raised after a loader extension is created.
+         * Observable raised after a loader extension is created.
          * Set additional options for a loader extension in this event.
          * Set additional options for a loader extension in this event.
          */
          */
         public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
         public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
 
 
         private _onExtensionLoadedObserver: Nullable<Observer<IGLTFLoaderExtension>>;
         private _onExtensionLoadedObserver: Nullable<Observer<IGLTFLoaderExtension>>;
+
         /**
         /**
-         * Raised after a loader extension is created. (onExtensionLoadedObservable is likely desired instead.)
+         * Callback raised after a loader extension is created.
          */
          */
         public set onExtensionLoaded(callback: (extension: IGLTFLoaderExtension) => void) {
         public set onExtensionLoaded(callback: (extension: IGLTFLoaderExtension) => void) {
             if (this._onExtensionLoadedObserver) {
             if (this._onExtensionLoadedObserver) {
@@ -322,7 +372,7 @@ module BABYLON {
 
 
         /**
         /**
          * Returns a promise that resolves when the asset is completely loaded.
          * Returns a promise that resolves when the asset is completely loaded.
-         * @returns A promise that resolves when the asset is completely loaded.
+         * @returns a promise that resolves when the asset is completely loaded.
          */
          */
         public whenCompleteAsync(): Promise<void> {
         public whenCompleteAsync(): Promise<void> {
             return new Promise(resolve => {
             return new Promise(resolve => {
@@ -333,7 +383,7 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-         * The loader state (LOADING, READY, COMPLETE) or null if the loader is not active.
+         * The loader state or null if the loader is not active.
          */
          */
         public get loaderState(): Nullable<GLTFLoaderState> {
         public get loaderState(): Nullable<GLTFLoaderState> {
             return this._loader ? this._loader.state : null;
             return this._loader ? this._loader.state : null;
@@ -368,20 +418,23 @@ module BABYLON {
             this.onMeshLoadedObservable.clear();
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
+            this.onCameraLoadedObservable.clear();
+            this.onCompleteObservable.clear();
+            this.onExtensionLoadedObservable.clear();
 
 
             this.onDisposeObservable.notifyObservers(this);
             this.onDisposeObservable.notifyObservers(this);
             this.onDisposeObservable.clear();
             this.onDisposeObservable.clear();
         }
         }
 
 
         /**
         /**
-        * Imports one or more meshes from a loaded gltf file and adds them to the scene
-        * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
-        * @param scene the scene the meshes should be added to
-        * @param data gltf data containing information of the meshes in a loaded file
-        * @param rootUrl root url to load from
-        * @param onProgress event that fires when loading progress has occured
-        * @returns a promise containg the loaded meshes, particles, skeletons and animations
-        */
+         * Imports one or more meshes from the loaded glTF data and adds them to the scene
+         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
+         * @param scene the scene the meshes should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @returns a promise containg the loaded meshes, particles, skeletons and animations
+         */
         public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
         public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
             return Promise.resolve().then(() => {
             return Promise.resolve().then(() => {
                 const loaderData = this._parse(data);
                 const loaderData = this._parse(data);
@@ -391,13 +444,13 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-        * Imports all objects from a loaded gltf file and adds them to the scene
-        * @param scene the scene the objects should be added to
-        * @param data gltf data containing information of the meshes in a loaded file
-        * @param rootUrl root url to load from
-        * @param onProgress event that fires when loading progress has occured
-        * @returns a promise which completes when objects have been loaded to the scene
-        */
+         * Imports all objects from the loaded glTF data and adds them to the scene
+         * @param scene the scene the objects should be added to
+         * @param data the glTF data to load
+         * @param rootUrl root url to load from
+         * @param onProgress event that fires when loading progress has occured
+         * @returns a promise which completes when objects have been loaded to the scene
+         */
         public loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
         public loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
             return Promise.resolve().then(() => {
             return Promise.resolve().then(() => {
                 const loaderData = this._parse(data);
                 const loaderData = this._parse(data);
@@ -431,7 +484,7 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-         * If the data string can be loaded directly
+         * If the data string can be loaded directly.
          * @param data string contianing the file data
          * @param data string contianing the file data
          * @returns if the data can be loaded directly
          * @returns if the data can be loaded directly
          */
          */
@@ -440,12 +493,12 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-         * Rewrites a url by combining a root url and response url
+         * Rewrites a url by combining a root url and response url.
          */
          */
         public rewriteRootURL: (rootUrl: string, responseURL?: string) => string;
         public rewriteRootURL: (rootUrl: string, responseURL?: string) => string;
 
 
         /**
         /**
-         * Instantiates a gltf file loader plugin
+         * Instantiates a glTF file loader plugin.
          * @returns the created plugin
          * @returns the created plugin
          */
          */
         public createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync {
         public createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync {
@@ -510,12 +563,18 @@ module BABYLON {
             loader.onMeshLoadedObservable.add(mesh => this.onMeshLoadedObservable.notifyObservers(mesh));
             loader.onMeshLoadedObservable.add(mesh => this.onMeshLoadedObservable.notifyObservers(mesh));
             loader.onTextureLoadedObservable.add(texture => this.onTextureLoadedObservable.notifyObservers(texture));
             loader.onTextureLoadedObservable.add(texture => this.onTextureLoadedObservable.notifyObservers(texture));
             loader.onMaterialLoadedObservable.add(material => this.onMaterialLoadedObservable.notifyObservers(material));
             loader.onMaterialLoadedObservable.add(material => this.onMaterialLoadedObservable.notifyObservers(material));
-            loader.onExtensionLoadedObservable.add(extension => this.onExtensionLoadedObservable.notifyObservers(extension));
+            loader.onCameraLoadedObservable.add(camera => this.onCameraLoadedObservable.notifyObservers(camera));
+
+            loader.onExtensionLoadedObservable.add(extension => {
+                this.onExtensionLoadedObservable.notifyObservers(extension);
+                this.onExtensionLoadedObservable.clear();
+            });
 
 
             loader.onCompleteObservable.add(() => {
             loader.onCompleteObservable.add(() => {
                 this.onMeshLoadedObservable.clear();
                 this.onMeshLoadedObservable.clear();
                 this.onTextureLoadedObservable.clear();
                 this.onTextureLoadedObservable.clear();
                 this.onMaterialLoadedObservable.clear();
                 this.onMaterialLoadedObservable.clear();
+                this.onCameraLoadedObservable.clear();
 
 
                 this.onCompleteObservable.notifyObservers(this);
                 this.onCompleteObservable.notifyObservers(this);
                 this.onCompleteObservable.clear();
                 this.onCompleteObservable.clear();

+ 1 - 6
sandbox/index.js

@@ -92,11 +92,6 @@ if (BABYLON.Engine.isSupported()) {
         // Fix for IE, otherwise it will change the default filter for files selection after first use
         // Fix for IE, otherwise it will change the default filter for files selection after first use
         htmlInput.value = "";
         htmlInput.value = "";
 
 
-        // removing glTF created camera
-        if (currentScene.activeCamera && currentPluginName === "gltf") {
-            currentScene.activeCamera.dispose();
-            currentScene.activeCamera = null;
-        }
         // Attach camera to canvas inputs
         // Attach camera to canvas inputs
         if (!currentScene.activeCamera || currentScene.lights.length === 0) {
         if (!currentScene.activeCamera || currentScene.lights.length === 0) {
             currentScene.createDefaultCameraOrLight(true);
             currentScene.createDefaultCameraOrLight(true);
@@ -265,7 +260,7 @@ if (BABYLON.Engine.isSupported()) {
 
 
     window.addEventListener("keydown", function (evt) {
     window.addEventListener("keydown", function (evt) {
         // Press Esc to toggle footer
         // Press Esc to toggle footer
-        if (evt.keyCode === 27) {
+        if (evt.keyCode === 27 &&!enableDebugLayer) {
             if (footer.style.display === "none") {
             if (footer.style.display === "none") {
                 footer.style.display = "block";
                 footer.style.display = "block";
             }
             }

+ 710 - 0
serializers/src/glTF/2.0/babylon.glTFAnimation.ts

@@ -0,0 +1,710 @@
+/// <reference path="../../../../dist/babylon.glTF2Interface.d.ts"/>
+
+module BABYLON.GLTF2 {
+    /**
+     * @hidden
+     * Interface to store animation data.
+     */
+    export interface _IAnimationData {
+        /**
+         * Keyframe data.
+         */
+        inputs: number[],
+        /**
+         * Value data.
+         */
+        outputs: number[][],
+        /**
+         * Animation interpolation data.
+         */
+        samplerInterpolation: AnimationSamplerInterpolation,
+        /**
+         * Minimum keyframe value.
+         */
+        inputsMin: number,
+        /**
+         * Maximum keyframe value.
+         */
+        inputsMax: number,
+    }
+
+    /**
+     * @hidden
+     */
+    export interface _IAnimationInfo {
+        /**
+         * The target channel for the animation
+         */
+        animationChannelTargetPath: AnimationChannelTargetPath,
+        /**
+         * The glTF accessor type for the data.
+         */
+        dataAccessorType: AccessorType.VEC3 | AccessorType.VEC4,
+        /**
+         * Specifies if quaternions should be used.
+         */
+        useQuaternion: boolean
+    }
+
+    /**
+     * @hidden
+     * Enum for handling in tangent and out tangent.
+     */
+    enum _TangentType {
+        /**
+         * Specifies that input tangents are used.
+         */
+        INTANGENT,
+        /**
+         * Specifies that output tangents are used.
+         */
+        OUTTANGENT
+    }
+    /**
+     * @hidden
+     * Utility class for generating glTF animation data from BabylonJS.
+     */
+    export class _GLTFAnimation {
+        /**
+         * 
+         * Creates glTF channel animation from BabylonJS animation.
+         * @param babylonMesh - BabylonJS mesh.
+         * @param animation - animation.
+         * @param animationChannelTargetPath - The target animation channel. 
+         * @param convertToRightHandedSystem - Specifies if the values should be converted to right-handed.
+         * @param useQuaternion - Specifies if quaternions are used.
+         * @returns nullable IAnimationData
+         */
+        public static _CreateNodeAnimation(babylonMesh: BABYLON.Mesh, animation: Animation, animationChannelTargetPath: AnimationChannelTargetPath, convertToRightHandedSystem: boolean, useQuaternion: boolean, animationSampleRate: number): Nullable<_IAnimationData> {
+            const inputs: number[] = [];
+            const outputs: number[][] = [];
+            const keyFrames = animation.getKeys();
+            const minMaxKeyFrames = _GLTFAnimation.calculateMinMaxKeyFrames(keyFrames);
+            const interpolationOrBake = _GLTFAnimation._DeduceInterpolation(keyFrames, animationChannelTargetPath, useQuaternion);
+            const frameDelta = minMaxKeyFrames.max - minMaxKeyFrames.min;
+
+            const interpolation = interpolationOrBake.interpolationType;
+            const shouldBakeAnimation = interpolationOrBake.shouldBakeAnimation;
+
+            if (shouldBakeAnimation) {
+                _GLTFAnimation._CreateBakedAnimation(babylonMesh, animation, animationChannelTargetPath, minMaxKeyFrames.min, minMaxKeyFrames.max, animation.framePerSecond, animationSampleRate, inputs, outputs, minMaxKeyFrames, convertToRightHandedSystem, useQuaternion);
+            }
+            else {
+                if (interpolation === AnimationSamplerInterpolation.LINEAR || interpolation === AnimationSamplerInterpolation.STEP) {
+                    _GLTFAnimation._CreateLinearOrStepAnimation(babylonMesh, animation, animationChannelTargetPath, frameDelta, inputs, outputs, convertToRightHandedSystem, useQuaternion);
+
+                }
+                else if (interpolation === AnimationSamplerInterpolation.CUBICSPLINE) {
+                    _GLTFAnimation._CreateCubicSplineAnimation(babylonMesh, animation, animationChannelTargetPath, frameDelta, inputs, outputs, convertToRightHandedSystem, useQuaternion);
+                }
+                else {
+                    _GLTFAnimation._CreateBakedAnimation(babylonMesh, animation, animationChannelTargetPath, minMaxKeyFrames.min, minMaxKeyFrames.max, animation.framePerSecond, animationSampleRate, inputs, outputs, minMaxKeyFrames, convertToRightHandedSystem, useQuaternion);
+                }
+            }
+
+            if (inputs.length && outputs.length) {
+                const result: _IAnimationData = {
+                    inputs: inputs,
+                    outputs: outputs,
+                    samplerInterpolation: interpolation,
+                    inputsMin: shouldBakeAnimation ? minMaxKeyFrames.min : Tools.FloatRound(minMaxKeyFrames.min / animation.framePerSecond),
+                    inputsMax: shouldBakeAnimation ? minMaxKeyFrames.max : Tools.FloatRound(minMaxKeyFrames.max / animation.framePerSecond)
+                }
+
+                return result;
+            }
+
+            return null;
+        }
+
+        private static _DeduceAnimationInfo(animation: Animation): Nullable<_IAnimationInfo> {
+            let animationChannelTargetPath: Nullable<AnimationChannelTargetPath> = null;
+            let dataAccessorType = AccessorType.VEC3;
+            let useQuaternion: boolean = false;
+            let property = animation.targetProperty.split('.');
+            switch (property[0]) {
+                case 'scaling': {
+                    animationChannelTargetPath = AnimationChannelTargetPath.SCALE;
+                    break;
+                }
+                case 'position': {
+                    animationChannelTargetPath = AnimationChannelTargetPath.TRANSLATION;
+                    break;
+                }
+                case 'rotation': {
+                    dataAccessorType = AccessorType.VEC4;
+                    animationChannelTargetPath = AnimationChannelTargetPath.ROTATION;
+                    break;
+                }
+                case 'rotationQuaternion': {
+                    dataAccessorType = AccessorType.VEC4;
+                    useQuaternion = true;
+                    animationChannelTargetPath = AnimationChannelTargetPath.ROTATION;
+                    break;
+                }
+                default: {
+                    Tools.Error(`Unsupported animatable property ${property[0]}`);
+                }
+            }
+            if (animationChannelTargetPath) {
+                return { animationChannelTargetPath: animationChannelTargetPath, dataAccessorType: dataAccessorType, useQuaternion: useQuaternion };
+            }
+            else {
+                Tools.Error('animation channel target path and data accessor type could be deduced');
+            }
+            return null;
+        }
+
+        /**
+         * 
+         * @param babylonMesh 
+         * @param runtimeGLTFAnimation 
+         * @param idleGLTFAnimations 
+         * @param nodeMap 
+         * @param nodes 
+         * @param binaryWriter 
+         * @param bufferViews 
+         * @param accessors 
+         * @param convertToRightHandedSystem 
+         */
+        public static _CreateNodeAnimationFromMeshAnimations(babylonMesh: Mesh, runtimeGLTFAnimation: IAnimation, idleGLTFAnimations: IAnimation[], nodeMap: { [key: number]: number }, nodes: INode[], binaryWriter: _BinaryWriter, bufferViews: IBufferView[], accessors: IAccessor[], convertToRightHandedSystem: boolean, animationSampleRate: number) {
+            let glTFAnimation: IAnimation;
+            if (babylonMesh.animations) {
+                babylonMesh.animations.forEach(function (animation) {
+                    let animationInfo = _GLTFAnimation._DeduceAnimationInfo(animation);
+                    if (animationInfo) {
+                        glTFAnimation = {
+                            name: animation.name,
+                            samplers: [],
+                            channels: []
+                        }
+                        _GLTFAnimation.AddAnimation(`${animation.name}`,
+                            animation.hasRunningRuntimeAnimations ? runtimeGLTFAnimation : glTFAnimation,
+                            babylonMesh,
+                            animation,
+                            animationInfo.dataAccessorType,
+                            animationInfo.animationChannelTargetPath,
+                            nodeMap,
+                            binaryWriter,
+                            bufferViews,
+                            accessors,
+                            convertToRightHandedSystem,
+                            animationInfo.useQuaternion,
+                            animationSampleRate
+                        );
+                        if (glTFAnimation.samplers.length && glTFAnimation.channels.length) {
+                            idleGLTFAnimations.push(glTFAnimation);
+                        }
+                    }
+                });
+            }
+        }
+
+        /**
+         * 
+         * @param babylonScene 
+         * @param glTFAnimations 
+         * @param nodeMap 
+         * @param nodes 
+         * @param binaryWriter 
+         * @param bufferViews 
+         * @param accessors 
+         * @param convertToRightHandedSystem 
+         */
+        public static _CreateNodeAnimationFromAnimationGroups(babylonScene: Scene, glTFAnimations: IAnimation[], nodeMap: { [key: number]: number }, nodes: INode[], binaryWriter: _BinaryWriter, bufferViews: IBufferView[], accessors: IAccessor[], convertToRightHandedSystem: boolean, animationSampleRate: number) {
+            let glTFAnimation: IAnimation;
+            if (babylonScene.animationGroups) {
+                let animationGroups = babylonScene.animationGroups;
+
+                animationGroups.forEach(function (animationGroup) {
+                    glTFAnimation = {
+                        name: animationGroup.name,
+                        channels: [],
+                        samplers: []
+                    }
+                    animationGroup.targetedAnimations.forEach(function (targetAnimation) {
+                        let target = targetAnimation.target;
+                        let animation = targetAnimation.animation;
+                        if (target instanceof Mesh) {
+                            let animationInfo = _GLTFAnimation._DeduceAnimationInfo(targetAnimation.animation);
+                            if (animationInfo) {
+                                let babylonMesh = target as Mesh;
+                                _GLTFAnimation.AddAnimation(`${animation.name}`,
+                                    glTFAnimation,
+                                    babylonMesh,
+                                    animation,
+                                    animationInfo.dataAccessorType,
+                                    animationInfo.animationChannelTargetPath,
+                                    nodeMap,
+                                    binaryWriter,
+                                    bufferViews,
+                                    accessors,
+                                    convertToRightHandedSystem,
+                                    animationInfo.useQuaternion,
+                                    animationSampleRate
+                                );
+                            }
+                        }
+                    });
+                    if (glTFAnimation.channels.length && glTFAnimation.samplers.length) {
+                        glTFAnimations.push(glTFAnimation);
+                    }
+                });
+            }
+        }
+
+        private static AddAnimation(name: string, glTFAnimation: IAnimation, babylonMesh: Mesh, animation: Animation, dataAccessorType: AccessorType, animationChannelTargetPath: AnimationChannelTargetPath, nodeMap: { [key: number]: number }, binaryWriter: _BinaryWriter, bufferViews: IBufferView[], accessors: IAccessor[], convertToRightHandedSystem: boolean, useQuaternion: boolean, animationSampleRate: number) {
+            let animationData = _GLTFAnimation._CreateNodeAnimation(babylonMesh, animation, animationChannelTargetPath, convertToRightHandedSystem, useQuaternion, animationSampleRate);
+            let bufferView: IBufferView;
+            let accessor: IAccessor;
+            let keyframeAccessorIndex: number;
+            let dataAccessorIndex: number;
+            let outputLength: number;
+            let animationSampler: IAnimationSampler;
+            let animationChannel: IAnimationChannel;
+
+            if (animationData) {
+                let nodeIndex = nodeMap[babylonMesh.uniqueId];
+
+                // Creates buffer view and accessor for key frames.
+                let byteLength = animationData.inputs.length * 4;
+                bufferView = _GLTFUtilities.CreateBufferView(0, binaryWriter.getByteOffset(), byteLength, undefined, `${name}  keyframe data view`);
+                bufferViews.push(bufferView);
+
+                animationData.inputs.forEach(function (input) {
+                    binaryWriter.setFloat32(input);
+                });
+
+                accessor = _GLTFUtilities.CreateAccessor(bufferViews.length - 1, `${name}  keyframes`, AccessorType.SCALAR, AccessorComponentType.FLOAT, animationData.inputs.length, null, [animationData.inputsMin], [animationData.inputsMax]);
+                accessors.push(accessor);
+                keyframeAccessorIndex = accessors.length - 1;
+
+                // create bufferview and accessor for keyed values.
+                outputLength = animationData.outputs.length;
+                byteLength = dataAccessorType === AccessorType.VEC3 ? animationData.outputs.length * 12 : animationData.outputs.length * 16;
+
+                // check for in and out tangents
+                bufferView = _GLTFUtilities.CreateBufferView(0, binaryWriter.getByteOffset(), byteLength, undefined, `${name}  data view`);
+                bufferViews.push(bufferView);
+
+                animationData.outputs.forEach(function (output) {
+                    output.forEach(function (entry) {
+                        binaryWriter.setFloat32(entry);
+                    });
+                });
+
+                accessor = _GLTFUtilities.CreateAccessor(bufferViews.length - 1, `${name}  data`, dataAccessorType, AccessorComponentType.FLOAT, outputLength, null, null, null);
+                accessors.push(accessor);
+                dataAccessorIndex = accessors.length - 1;
+
+                // create sampler
+                animationSampler = {
+                    interpolation: animationData.samplerInterpolation,
+                    input: keyframeAccessorIndex,
+                    output: dataAccessorIndex
+                }
+                glTFAnimation.samplers.push(animationSampler);
+
+                // create channel
+                animationChannel = {
+                    sampler: glTFAnimation.samplers.length - 1,
+                    target: {
+                        node: nodeIndex,
+                        path: animationChannelTargetPath
+                    }
+                }
+                glTFAnimation.channels.push(animationChannel);
+            }
+        }
+
+        /**
+         * Create a baked animation
+         * @param babylonMesh BabylonJS mesh
+         * @param animation BabylonJS animation corresponding to the BabylonJS mesh
+         * @param animationChannelTargetPath animation target channel
+         * @param minFrame minimum animation frame
+         * @param maxFrame maximum animation frame
+         * @param fps frames per second of the animation
+         * @param inputs input key frames of the animation
+         * @param outputs output key frame data of the animation
+         * @param convertToRightHandedSystem converts the values to right-handed
+         * @param useQuaternion specifies if quaternions should be used
+         */
+        private static _CreateBakedAnimation(babylonMesh: Mesh, animation: Animation, animationChannelTargetPath: AnimationChannelTargetPath, minFrame: number, maxFrame: number, fps: number, sampleRate: number, inputs: number[], outputs: number[][], minMaxFrames: { min: number, max: number }, convertToRightHandedSystem: boolean, useQuaternion: boolean) {
+            let value: number | Vector3 | Quaternion;
+            let quaternionCache: Quaternion = Quaternion.Identity();
+            let previousTime: Nullable<number> = null;
+            let time: number;
+            let maxUsedFrame: Nullable<number> = null;
+            let currKeyFrame: Nullable<IAnimationKey> = null;
+            let nextKeyFrame: Nullable<IAnimationKey> = null;
+            let prevKeyFrame: Nullable<IAnimationKey> = null;
+            let endFrame: Nullable<number> = null;
+            minMaxFrames.min = Tools.FloatRound(minFrame / fps);
+
+            let keyFrames = animation.getKeys();
+
+            for (let i = 0, length = keyFrames.length; i < length; ++i) {
+                endFrame = null;
+                currKeyFrame = keyFrames[i];
+
+                if (i + 1 < length) {
+                    nextKeyFrame = keyFrames[i + 1];
+                    if (currKeyFrame.value.equals(nextKeyFrame.value)) {
+                        if (i === 0) { // set the first frame to itself
+                            endFrame = currKeyFrame.frame;
+                        }
+                        else {
+                            continue;
+                        }
+                    }
+                    else {
+                        endFrame = nextKeyFrame.frame;
+                    }
+                }
+                else {
+                    // at the last key frame
+                    prevKeyFrame = keyFrames[i - 1];
+                    if (currKeyFrame.value.equals(prevKeyFrame.value)) {
+                        continue;
+                    }
+                    else {
+                        endFrame = maxFrame;
+                    }
+                }
+                if (endFrame) {
+                    for (let f = currKeyFrame.frame; f <= endFrame; f += sampleRate) {
+                        time = Tools.FloatRound(f / fps);
+                        if (time === previousTime) {
+                            continue;
+                        }
+                        previousTime = time;
+                        maxUsedFrame = time;
+                        value = animation._interpolate(f, 0, undefined, animation.loopMode);
+
+                        _GLTFAnimation._SetInterpolatedValue(babylonMesh, value, time, animation, animationChannelTargetPath, quaternionCache, inputs, outputs, convertToRightHandedSystem, useQuaternion);
+                    }
+                }
+            }
+            if (maxUsedFrame) {
+                minMaxFrames.max = maxUsedFrame;
+            }
+        }
+
+        private static _ConvertFactorToVector3OrQuaternion(factor: number, babylonMesh: Mesh, animation: Animation, animationType: number, animationChannelTargetPath: AnimationChannelTargetPath, convertToRightHandedSystem: boolean, useQuaternion: boolean): Nullable<Vector3 | Quaternion> {
+            let property: string[];
+            let componentName: string;
+            let value: Nullable<Quaternion | Vector3> = null;
+            const basePositionRotationOrScale = _GLTFAnimation._GetBasePositionRotationOrScale(babylonMesh, animationChannelTargetPath, convertToRightHandedSystem, useQuaternion);
+            if (animationType === Animation.ANIMATIONTYPE_FLOAT) { // handles single component x, y, z or w component animation by using a base property and animating over a component.
+                property = animation.targetProperty.split('.');
+                componentName = property ? property[1] : ''; // x, y, or z component
+                value = useQuaternion ? BABYLON.Quaternion.FromArray(basePositionRotationOrScale).normalize() : BABYLON.Vector3.FromArray(basePositionRotationOrScale);
+
+                switch (componentName) {
+                    case 'x':
+                    case 'y': {
+                        value[componentName] = (convertToRightHandedSystem && useQuaternion) ? -factor : factor;
+                        break;
+                    }
+                    case 'z': {
+                        value[componentName] = (convertToRightHandedSystem && !useQuaternion && !(animationChannelTargetPath === AnimationChannelTargetPath.SCALE)) ? -factor : factor;
+                        break;
+                    }
+                    case 'w': {
+                        (value as Quaternion).w = factor;
+                        break;
+                    }
+                    default: {
+                        Tools.Error(`glTFAnimation: Unsupported component type "${componentName}" for scale animation!`);
+                    }
+                }
+            }
+
+            return value;
+        }
+
+        private static _SetInterpolatedValue(babylonMesh: Mesh, value: Nullable<number | Vector3 | Quaternion>, time: number, animation: Animation, animationChannelTargetPath: AnimationChannelTargetPath, quaternionCache: Quaternion, inputs: number[], outputs: number[][], convertToRightHandedSystem: boolean, useQuaternion: boolean) {
+            const animationType = animation.dataType;
+            let cacheValue: Vector3 | Quaternion;
+            inputs.push(time);
+            if (typeof value === "number") {
+                value = this._ConvertFactorToVector3OrQuaternion(value as number, babylonMesh, animation, animationType, animationChannelTargetPath, convertToRightHandedSystem, useQuaternion);
+            }
+            if (value) {
+                if (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
+                    if (useQuaternion) {
+                        quaternionCache = value as Quaternion;
+                    }
+                    else {
+                        cacheValue = value as Vector3;
+                        Quaternion.RotationYawPitchRollToRef(cacheValue.y, cacheValue.x, cacheValue.z, quaternionCache);
+                    }
+                    if (convertToRightHandedSystem) {
+                        quaternionCache.x *= -1;
+                        quaternionCache.y *= -1;
+                        outputs.push(quaternionCache.asArray());
+                    }
+                }
+                else {
+                    cacheValue = value as Vector3;
+                    if (convertToRightHandedSystem && (animationChannelTargetPath !== AnimationChannelTargetPath.SCALE)) {
+                        cacheValue.z *= -1;
+                    }
+
+                    outputs.push(cacheValue.asArray());
+                }
+            }
+        }
+
+        /**
+         * Creates linear animation from the animation key frames
+         * @param babylonMesh BabylonJS mesh
+         * @param animation BabylonJS animation
+         * @param animationChannelTargetPath The target animation channel
+         * @param frameDelta The difference between the last and first frame of the animation
+         * @param inputs Array to store the key frame times
+         * @param outputs Array to store the key frame data
+         * @param convertToRightHandedSystem Specifies if the position data should be converted to right handed
+         * @param useQuaternion Specifies if quaternions are used in the animation
+         */
+        private static _CreateLinearOrStepAnimation(babylonMesh: Mesh, animation: Animation, animationChannelTargetPath: AnimationChannelTargetPath, frameDelta: number, inputs: number[], outputs: number[][], convertToRightHandedSystem: boolean, useQuaternion: boolean) {
+            animation.getKeys().forEach(function (keyFrame) {
+                inputs.push(keyFrame.frame / animation.framePerSecond); // keyframes in seconds.
+                _GLTFAnimation._AddKeyframeValue(keyFrame, animation, outputs, animationChannelTargetPath, babylonMesh, convertToRightHandedSystem, useQuaternion);
+            });
+        }
+
+        /**
+         * Creates cubic spline animation from the animation key frames
+         * @param babylonMesh BabylonJS mesh
+         * @param animation BabylonJS animation
+         * @param animationChannelTargetPath The target animation channel
+         * @param frameDelta The difference between the last and first frame of the animation
+         * @param inputs Array to store the key frame times
+         * @param outputs Array to store the key frame data
+         * @param convertToRightHandedSystem Specifies if the position data should be converted to right handed
+         * @param useQuaternion Specifies if quaternions are used in the animation
+         */
+        private static _CreateCubicSplineAnimation(babylonMesh: Mesh, animation: Animation, animationChannelTargetPath: AnimationChannelTargetPath, frameDelta: number, inputs: number[], outputs: number[][], convertToRightHandedSystem: boolean, useQuaternion: boolean) {
+            animation.getKeys().forEach(function (keyFrame) {
+                inputs.push(keyFrame.frame / animation.framePerSecond); // keyframes in seconds.
+                _GLTFAnimation.AddSplineTangent(
+                    _TangentType.INTANGENT,
+                    outputs,
+                    animationChannelTargetPath,
+                    AnimationSamplerInterpolation.CUBICSPLINE,
+                    keyFrame,
+                    frameDelta,
+                    useQuaternion,
+                    convertToRightHandedSystem
+                );
+                _GLTFAnimation._AddKeyframeValue(keyFrame, animation, outputs, animationChannelTargetPath, babylonMesh, convertToRightHandedSystem, useQuaternion);
+
+                _GLTFAnimation.AddSplineTangent(
+                    _TangentType.OUTTANGENT,
+                    outputs,
+                    animationChannelTargetPath,
+                    AnimationSamplerInterpolation.CUBICSPLINE,
+                    keyFrame,
+                    frameDelta,
+                    useQuaternion,
+                    convertToRightHandedSystem
+                );
+            });
+        }
+
+        private static _GetBasePositionRotationOrScale(babylonMesh: Mesh, animationChannelTargetPath: AnimationChannelTargetPath, convertToRightHandedSystem: boolean, useQuaternion: boolean) {
+            let basePositionRotationOrScale: number[];
+            if (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
+                if (useQuaternion) {
+                    if (babylonMesh.rotationQuaternion) {
+                        basePositionRotationOrScale = babylonMesh.rotationQuaternion.asArray();
+                        if (convertToRightHandedSystem) {
+                            basePositionRotationOrScale[0] *= -1;
+                            basePositionRotationOrScale[1] *= -1;
+                        }
+                    }
+                    else {
+                        basePositionRotationOrScale = BABYLON.Quaternion.Identity().asArray();
+                    }
+                }
+                else {
+                    basePositionRotationOrScale = babylonMesh.rotation.asArray();
+                    basePositionRotationOrScale[2] *= -1;
+                }
+            }
+            else if (animationChannelTargetPath === AnimationChannelTargetPath.TRANSLATION) {
+                basePositionRotationOrScale = babylonMesh.position.asArray();
+                if (convertToRightHandedSystem) {
+                    basePositionRotationOrScale[2] *= -1;
+                }
+            }
+            else { // scale
+                basePositionRotationOrScale = babylonMesh.scaling.asArray();
+            }
+            return basePositionRotationOrScale;
+        }
+
+        /**
+         * Adds a key frame value
+         * @param keyFrame 
+         * @param animation 
+         * @param outputs 
+         * @param animationChannelTargetPath 
+         * @param basePositionRotationOrScale 
+         * @param convertToRightHandedSystem 
+         * @param useQuaternion 
+         */
+        private static _AddKeyframeValue(keyFrame: IAnimationKey, animation: Animation, outputs: number[][], animationChannelTargetPath: AnimationChannelTargetPath, babylonMesh: Mesh, convertToRightHandedSystem: boolean, useQuaternion: boolean) {
+            let value: number[];
+            let newPositionRotationOrScale: Nullable<Vector3 | Quaternion>;
+            const animationType = animation.dataType;
+            if (animationType === Animation.ANIMATIONTYPE_VECTOR3) {
+                value = keyFrame.value.asArray();
+                if (convertToRightHandedSystem && !(animationChannelTargetPath === AnimationChannelTargetPath.SCALE)) {
+                    value[2] *= -1;
+                }
+                if (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
+                    outputs.push(Vector3.FromArray(value).toQuaternion().asArray());
+                }
+                else {
+                    outputs.push(value); // scale or position vector.
+                }
+            }
+            else if (animationType === Animation.ANIMATIONTYPE_FLOAT) { // handles single component x, y, z or w component animation by using a base property and animating over a component.
+                newPositionRotationOrScale = this._ConvertFactorToVector3OrQuaternion(keyFrame.value as number, babylonMesh, animation, animationType, animationChannelTargetPath, convertToRightHandedSystem, useQuaternion)
+                if (newPositionRotationOrScale) {
+                    if (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
+                        useQuaternion ? outputs.push(newPositionRotationOrScale.normalize().asArray()) : outputs.push((newPositionRotationOrScale as Vector3).toQuaternion().normalize().asArray());
+                    }
+                    else {
+                        outputs.push(newPositionRotationOrScale.asArray());
+                    }
+                }
+            }
+            else if (animationType === Animation.ANIMATIONTYPE_QUATERNION) {
+                value = (keyFrame.value as Quaternion).normalize().asArray();
+
+                if (convertToRightHandedSystem) {
+                    value[0] *= -1;
+                    value[1] *= -1;
+                }
+                outputs.push(value);
+            }
+            else {
+                Tools.Error('glTFAnimation: Unsupported key frame values for animation!');
+            }
+        }
+
+        private static _DeduceInterpolation(keyFrames: IAnimationKey[], animationChannelTargetPath: AnimationChannelTargetPath, useQuaternion: boolean): { interpolationType: AnimationSamplerInterpolation, shouldBakeAnimation: boolean } {
+            let interpolationType: AnimationSamplerInterpolation | undefined;
+            let shouldBakeAnimation = false;
+            let key: IAnimationKey;
+
+            if (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION && !useQuaternion) {
+                return { interpolationType: AnimationSamplerInterpolation.LINEAR, shouldBakeAnimation: true };
+            }
+
+            for (let i = 0, length = keyFrames.length; i < length; ++i) {
+                key = keyFrames[i];
+                if (key.inTangent || key.outTangent) {
+                    if (interpolationType) {
+                        if (interpolationType !== AnimationSamplerInterpolation.CUBICSPLINE) {
+                            interpolationType = AnimationSamplerInterpolation.LINEAR;
+                            shouldBakeAnimation = true;
+                            break;
+                        }
+                    }
+                    else {
+                        interpolationType = AnimationSamplerInterpolation.CUBICSPLINE;
+                    }
+                }
+                else {
+                    if (interpolationType) {
+                        if (interpolationType === AnimationSamplerInterpolation.CUBICSPLINE ||
+                            (key.interpolation && (key.interpolation === AnimationKeyInterpolation.STEP) && interpolationType !== AnimationSamplerInterpolation.STEP)) {
+                            interpolationType = AnimationSamplerInterpolation.LINEAR;
+                            shouldBakeAnimation = true;
+                            break;
+                        }
+                    }
+                    else {
+                        if (key.interpolation && (key.interpolation === AnimationKeyInterpolation.STEP)) {
+                            interpolationType = AnimationSamplerInterpolation.STEP;
+                        }
+                        else {
+                            interpolationType = AnimationSamplerInterpolation.LINEAR;
+                        }
+                    }
+                }
+            }
+            if (!interpolationType) {
+                interpolationType = AnimationSamplerInterpolation.LINEAR;
+            }
+
+            return { interpolationType: interpolationType, shouldBakeAnimation: shouldBakeAnimation };
+        }
+
+        /**
+         * Adds an input tangent or output tangent to the output data
+         * If an input tangent or output tangent is missing, it uses the zero vector or zero quaternion
+         * @param tangentType Specifies which type of tangent to handle (inTangent or outTangent)
+         * @param outputs The animation data by keyframe
+         * @param animationChannelTargetPath The target animation channel
+         * @param interpolation The interpolation type
+         * @param keyFrame The key frame with the animation data
+         * @param frameDelta Time difference between two frames used to scale the tangent by the frame delta
+         * @param useQuaternion Specifies if quaternions are used
+         * @param convertToRightHandedSystem Specifies if the values should be converted to right-handed
+         */
+        private static AddSplineTangent(tangentType: _TangentType, outputs: number[][], animationChannelTargetPath: AnimationChannelTargetPath, interpolation: AnimationSamplerInterpolation, keyFrame: IAnimationKey, frameDelta: number, useQuaternion: boolean, convertToRightHandedSystem: boolean) {
+            let tangent: number[];
+            let tangentValue: Vector3 | Quaternion = tangentType === _TangentType.INTANGENT ? keyFrame.inTangent : keyFrame.outTangent;
+            if (interpolation === AnimationSamplerInterpolation.CUBICSPLINE) {
+                if (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
+                    if (tangentValue) {
+                        tangent = useQuaternion ? (tangentValue as Quaternion).scale(frameDelta).asArray() : (tangentValue as Vector3).scale(frameDelta).toQuaternion().asArray();
+                        if (convertToRightHandedSystem) {
+                            tangent[0] *= -1;
+                            tangent[1] *= -1;
+                        }
+                    }
+                    else {
+                        tangent = [0, 0, 0, 0];
+                    }
+                }
+                else {
+                    if (tangentValue) {
+                        tangent = (tangentValue as Vector3).scale(frameDelta).asArray();
+                        if (convertToRightHandedSystem) {
+                            tangent[2] *= -1;
+                        }
+                    }
+                    else {
+                        tangent = [0, 0, 0];
+                    }
+                }
+
+                outputs.push(tangent);
+            }
+        }
+
+        /**
+         * Get the minimum and maximum key frames' frame values
+         * @param keyFrames animation key frames
+         * @returns the minimum and maximum key frame value
+         */
+        private static calculateMinMaxKeyFrames(keyFrames: IAnimationKey[]): { min: number, max: number } {
+            let min: number = Infinity;
+            let max: number = -Infinity;
+            keyFrames.forEach(function (keyFrame) {
+                min = Math.min(min, keyFrame.frame);
+                max = Math.max(max, keyFrame.frame);
+            });
+
+            return { min: min, max: max };
+
+        }
+    }
+}

+ 8 - 8
serializers/src/glTF/2.0/babylon.glTFData.ts

@@ -4,28 +4,28 @@ module BABYLON {
     /**
     /**
      * Class for holding and downloading glTF file data
      * Class for holding and downloading glTF file data
      */
      */
-    export class _GLTFData {
+    export class GLTFData {
         /**
         /**
-         * Object which contains the file name as the key and its data as the value.
+         * Object which contains the file name as the key and its data as the value
          */
          */
         glTFFiles: { [fileName: string]: string | Blob };
         glTFFiles: { [fileName: string]: string | Blob };
 
 
         /**
         /**
-         * Initializes the glTF file object.
+         * Initializes the glTF file object
          */
          */
         public constructor() {
         public constructor() {
             this.glTFFiles = {};
             this.glTFFiles = {};
         }
         }
 
 
         /**
         /**
-         * Downloads the glTF data as files based on their names and data.
+         * Downloads the glTF data as files based on their names and data
          */
          */
         public downloadFiles(): void {
         public downloadFiles(): void {
             /**
             /**
-            * Checks for a matching suffix at the end of a string (for ES5 and lower).
-            * @param str - Source string.
-            * @param suffix - Suffix to search for in the source string.
-            * @returns - Boolean indicating whether the suffix was found (true) or not (false).
+            * Checks for a matching suffix at the end of a string (for ES5 and lower)
+            * @param str Source string
+            * @param suffix Suffix to search for in the source string
+            * @returns Boolean indicating whether the suffix was found (true) or not (false)
             */
             */
             function endsWith(str: string, suffix: string): boolean {
             function endsWith(str: string, suffix: string): boolean {
                 return str.indexOf(suffix, str.length - suffix.length) !== -1;
                 return str.indexOf(suffix, str.length - suffix.length) !== -1;

File diff suppressed because it is too large
+ 402 - 390
serializers/src/glTF/2.0/babylon.glTFExporter.ts


+ 234 - 212
serializers/src/glTF/2.0/babylon.glTFMaterial.ts

@@ -2,60 +2,66 @@
 
 
 module BABYLON.GLTF2 {
 module BABYLON.GLTF2 {
     /** 
     /** 
-     * Interface for storing specular glossiness factors.
-    */
+     * Interface for storing specular glossiness factors
+     * @hidden
+     */
+
     interface _IPBRSpecularGlossiness {
     interface _IPBRSpecularGlossiness {
         /** 
         /** 
-         * Represents the linear diffuse factors of the material.
+         * Represents the linear diffuse factors of the material
         */
         */
         diffuseColor: BABYLON.Color3;
         diffuseColor: BABYLON.Color3;
         /** 
         /** 
-         * Represents the linear specular factors of the material.
+         * Represents the linear specular factors of the material
         */
         */
         specularColor: BABYLON.Color3;
         specularColor: BABYLON.Color3;
         /** 
         /** 
-         * Represents the smoothness of the material.
+         * Represents the smoothness of the material
         */
         */
         glossiness: number;
         glossiness: number;
     }
     }
 
 
     /** 
     /** 
-     * Interface for storing metallic roughness factors.
-    */
+     * Interface for storing metallic roughness factors
+     * @hidden
+     */
+
     interface _IPBRMetallicRoughness {
     interface _IPBRMetallicRoughness {
         /** 
         /** 
-         * Represents the albedo color of the material.
+         * Represents the albedo color of the material
         */
         */
         baseColor: BABYLON.Color3;
         baseColor: BABYLON.Color3;
         /** 
         /** 
-         * Represents the metallness of the material.
+         * Represents the metallness of the material
         */
         */
         metallic: number;
         metallic: number;
         /** 
         /** 
-         * Represents the roughness of the material.
+         * Represents the roughness of the material
         */
         */
         roughness: number;
         roughness: number;
         /** 
         /** 
-         * The metallic roughness texture as a base64 string.
+         * The metallic roughness texture as a base64 string
         */
         */
         metallicRoughnessTextureBase64?: Nullable<string>;
         metallicRoughnessTextureBase64?: Nullable<string>;
         /** 
         /** 
-         * The base color texture as a base64 string.
+         * The base color texture as a base64 string
         */
         */
         baseColorTextureBase64?: Nullable<string>;
         baseColorTextureBase64?: Nullable<string>;
     }
     }
 
 
     /**
     /**
-     * Utility methods for working with glTF material conversion properties.  This class should only be used internally.
+     * Utility methods for working with glTF material conversion properties.  This class should only be used internally
+     * @hidden
+
      */
      */
     export class _GLTFMaterial {
     export class _GLTFMaterial {
         /**
         /**
-         * Represents the dielectric specular values for R, G and B.
+         * Represents the dielectric specular values for R, G and B
          */
          */
         private static readonly _dielectricSpecular: Color3 = new Color3(0.04, 0.04, 0.04);
         private static readonly _dielectricSpecular: Color3 = new Color3(0.04, 0.04, 0.04);
 
 
         /**
         /**
-         * Allows the maximum specular power to be defined for material calculations.
+         * Allows the maximum specular power to be defined for material calculations
          */
          */
         private static _maxSpecularPower = 1024;
         private static _maxSpecularPower = 1024;
 
 
@@ -65,10 +71,10 @@ module BABYLON.GLTF2 {
         private static _epsilon = 1e-6;
         private static _epsilon = 1e-6;
 
 
         /**
         /**
-         * Specifies if two colors are approximately equal in value.
-         * @param color1 - first color to compare to.
-         * @param color2 - second color to compare to.
-         * @param epsilon - threshold value
+         * Specifies if two colors are approximately equal in value
+         * @param color1 first color to compare to
+         * @param color2 second color to compare to
+         * @param epsilon threshold value
          */
          */
         private static FuzzyEquals(color1: Color3, color2: Color3, epsilon: number): boolean {
         private static FuzzyEquals(color1: Color3, color2: Color3, epsilon: number): boolean {
             return Scalar.WithinEpsilon(color1.r, color2.r, epsilon) &&
             return Scalar.WithinEpsilon(color1.r, color2.r, epsilon) &&
@@ -77,14 +83,14 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Gets the materials from a Babylon scene and converts them to glTF materials.
-         * @param scene - babylonjs scene.
-         * @param mimeType - texture mime type.
-         * @param images - array of images.
-         * @param textures - array of textures.
-         * @param materials - array of materials.
-         * @param imageData - mapping of texture names to base64 textures
-         * @param hasTextureCoords - specifies if texture coordinates are present on the material.
+         * Gets the materials from a Babylon scene and converts them to glTF materials
+         * @param scene babylonjs scene
+         * @param mimeType texture mime type
+         * @param images array of images
+         * @param textures array of textures
+         * @param materials array of materials
+         * @param imageData mapping of texture names to base64 textures
+         * @param hasTextureCoords specifies if texture coordinates are present on the material
          */
          */
         public static _ConvertMaterialsToGLTF(babylonMaterials: Material[], mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean) {
         public static _ConvertMaterialsToGLTF(babylonMaterials: Material[], mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean) {
             for (let i = 0; i < babylonMaterials.length; ++i) {
             for (let i = 0; i < babylonMaterials.length; ++i) {
@@ -99,14 +105,14 @@ module BABYLON.GLTF2 {
                     _GLTFMaterial._ConvertPBRMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
                     _GLTFMaterial._ConvertPBRMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
                 }
                 }
                 else {
                 else {
-                    throw new Error("Unsupported material type: " + babylonMaterial.name);
+                    Tools.Error("Unsupported material type: " + babylonMaterial.name);
                 }
                 }
             }
             }
         }
         }
 
 
         /**
         /**
-         * Makes a copy of the glTF material without the texture parameters.
-         * @param originalMaterial - original glTF material.
+         * Makes a copy of the glTF material without the texture parameters
+         * @param originalMaterial original glTF material
          * @returns glTF material without texture parameters
          * @returns glTF material without texture parameters
          */
          */
         public static _StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial {
         public static _StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial {
@@ -129,8 +135,8 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Specifies if the material has any texture parameters present.
-         * @param material - glTF Material.
+         * Specifies if the material has any texture parameters present
+         * @param material glTF Material
          * @returns boolean specifying if texture parameters are present
          * @returns boolean specifying if texture parameters are present
          */
          */
         public static _HasTexturesPresent(material: IMaterial): boolean {
         public static _HasTexturesPresent(material: IMaterial): boolean {
@@ -148,9 +154,9 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
+         * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material
          * @param babylonStandardMaterial 
          * @param babylonStandardMaterial 
-         * @returns - glTF Metallic Roughness Material representation
+         * @returns glTF Metallic Roughness Material representation
          */
          */
         public static _ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness {
         public static _ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness {
             const P0 = new BABYLON.Vector2(0, 1);
             const P0 = new BABYLON.Vector2(0, 1);
@@ -159,13 +165,13 @@ module BABYLON.GLTF2 {
             const P3 = new BABYLON.Vector2(1300, 0.1);
             const P3 = new BABYLON.Vector2(1300, 0.1);
 
 
             /**
             /**
-             * Given the control points, solve for x based on a given t for a cubic bezier curve.
-             * @param t - a value between 0 and 1.
-             * @param p0 - first control point.
-             * @param p1 - second control point.
-             * @param p2 - third control point.
-             * @param p3 - fourth control point.
-             * @returns - number result of cubic bezier curve at the specified t.
+             * Given the control points, solve for x based on a given t for a cubic bezier curve
+             * @param t a value between 0 and 1
+             * @param p0 first control point
+             * @param p1 second control point
+             * @param p2 third control point
+             * @param p3 fourth control point
+             * @returns number result of cubic bezier curve at the specified t
              */
              */
             function _cubicBezierCurve(t: number, p0: number, p1: number, p2: number, p3: number): number {
             function _cubicBezierCurve(t: number, p0: number, p1: number, p2: number, p3: number): number {
                 return (
                 return (
@@ -179,9 +185,9 @@ module BABYLON.GLTF2 {
             /**
             /**
              * Evaluates a specified specular power value to determine the appropriate roughness value, 
              * Evaluates a specified specular power value to determine the appropriate roughness value, 
              * based on a pre-defined cubic bezier curve with specular on the abscissa axis (x-axis) 
              * based on a pre-defined cubic bezier curve with specular on the abscissa axis (x-axis) 
-             * and roughness on the ordinant axis (y-axis).
-             * @param specularPower - specular power of standard material.
-             * @returns - Number representing the roughness value.
+             * and roughness on the ordinant axis (y-axis)
+             * @param specularPower specular power of standard material
+             * @returns Number representing the roughness value
              */
              */
             function _solveForRoughness(specularPower: number): number {
             function _solveForRoughness(specularPower: number): number {
                 var t = Math.pow(specularPower / P3.x, 0.333333);
                 var t = Math.pow(specularPower / P3.x, 0.333333);
@@ -210,10 +216,10 @@ module BABYLON.GLTF2 {
 
 
         /**
         /**
          * Computes the metallic factor
          * Computes the metallic factor
-         * @param diffuse - diffused value
-         * @param specular - specular value
-         * @param oneMinusSpecularStrength - one minus the specular strength
-         * @returns - metallic value
+         * @param diffuse diffused value
+         * @param specular specular value
+         * @param oneMinusSpecularStrength one minus the specular strength
+         * @returns metallic value
          */
          */
         public static _SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number {
         public static _SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number {
             if (specular < _GLTFMaterial._dielectricSpecular.r) {
             if (specular < _GLTFMaterial._dielectricSpecular.r) {
@@ -230,10 +236,10 @@ module BABYLON.GLTF2 {
 
 
         /**
         /**
          * Gets the glTF alpha mode from the Babylon Material
          * Gets the glTF alpha mode from the Babylon Material
-         * @param babylonMaterial - Babylon Material
-         * @returns - The Babylon alpha mode value
+         * @param babylonMaterial Babylon Material
+         * @returns The Babylon alpha mode value
          */
          */
-        public static _GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode {
+        public static _GetAlphaMode(babylonMaterial: Material): Nullable<MaterialAlphaMode> {
             if (babylonMaterial instanceof StandardMaterial) {
             if (babylonMaterial instanceof StandardMaterial) {
                 const babylonStandardMaterial = babylonMaterial as StandardMaterial;
                 const babylonStandardMaterial = babylonMaterial as StandardMaterial;
                 if ((babylonStandardMaterial.alpha != 1.0) ||
                 if ((babylonStandardMaterial.alpha != 1.0) ||
@@ -263,7 +269,8 @@ module BABYLON.GLTF2 {
                         return MaterialAlphaMode.BLEND;
                         return MaterialAlphaMode.BLEND;
                     }
                     }
                     default: {
                     default: {
-                        throw new Error("Unsupported alpha mode " + babylonPBRMetallicRoughness.transparencyMode);
+                        Tools.Error("Unsupported alpha mode " + babylonPBRMetallicRoughness.transparencyMode);
+                        return null;
                     }
                     }
                 }
                 }
             }
             }
@@ -285,27 +292,28 @@ module BABYLON.GLTF2 {
                         return MaterialAlphaMode.BLEND;
                         return MaterialAlphaMode.BLEND;
                     }
                     }
                     default: {
                     default: {
-                        throw new Error("Unsupported alpha mode " + babylonPBRMaterial.transparencyMode);
+                        Tools.Error("Unsupported alpha mode " + babylonPBRMaterial.transparencyMode);
+                        return null;
                     }
                     }
                 }
                 }
             }
             }
             else {
             else {
-                throw new Error("Unsupported Babylon material type");
+                Tools.Error("Unsupported Babylon material type");
+                return null;
             }
             }
         }
         }
 
 
         /**
         /**
-         * Converts a Babylon Standard Material to a glTF Material.
-         * @param babylonStandardMaterial - BJS Standard Material.
-         * @param mimeType - mime type to use for the textures.
-         * @param images - array of glTF image interfaces.
-         * @param textures - array of glTF texture interfaces.
-         * @param materials - array of glTF material interfaces.
-         * @param imageData - map of image file name to data.
-         * @param hasTextureCoords - specifies if texture coordinates are present on the submesh to determine if textures should be applied.
+         * Converts a Babylon Standard Material to a glTF Material
+         * @param babylonStandardMaterial BJS Standard Material
+         * @param mimeType mime type to use for the textures
+         * @param images array of glTF image interfaces
+         * @param textures array of glTF texture interfaces
+         * @param materials array of glTF material interfaces
+         * @param imageData map of image file name to data
+         * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
          */
         public static _ConvertStandardMaterial(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean) {
         public static _ConvertStandardMaterial(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean) {
-            Tools.Warn(babylonStandardMaterial.name + ": Standard Material is currently not fully supported/implemented in glTF serializer");
             const glTFPbrMetallicRoughness = _GLTFMaterial._ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
             const glTFPbrMetallicRoughness = _GLTFMaterial._ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
 
 
             const glTFMaterial: IMaterial = { name: babylonStandardMaterial.name };
             const glTFMaterial: IMaterial = { name: babylonStandardMaterial.name };
@@ -366,14 +374,14 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Converts a Babylon PBR Metallic Roughness Material to a glTF Material.
-         * @param babylonPBRMetalRoughMaterial - BJS PBR Metallic Roughness Material.
-         * @param mimeType - mime type to use for the textures.
-         * @param images - array of glTF image interfaces.
-         * @param textures - array of glTF texture interfaces.
-         * @param materials - array of glTF material interfaces.
-         * @param imageData - map of image file name to data.
-         * @param hasTextureCoords - specifies if texture coordinates are present on the submesh to determine if textures should be applied.
+         * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
+         * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material
+         * @param mimeType mime type to use for the textures
+         * @param images array of glTF image interfaces
+         * @param textures array of glTF texture interfaces
+         * @param materials array of glTF material interfaces
+         * @param imageData map of image file name to data
+         * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
          */
         public static _ConvertPBRMetallicRoughnessMaterial(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean) {
         public static _ConvertPBRMetallicRoughnessMaterial(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean) {
             const glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness = {};
             const glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness = {};
@@ -436,11 +444,12 @@ module BABYLON.GLTF2 {
             }
             }
             if (babylonPBRMetalRoughMaterial.transparencyMode != null) {
             if (babylonPBRMetalRoughMaterial.transparencyMode != null) {
                 const alphaMode = _GLTFMaterial._GetAlphaMode(babylonPBRMetalRoughMaterial);
                 const alphaMode = _GLTFMaterial._GetAlphaMode(babylonPBRMetalRoughMaterial);
-
-                if (alphaMode !== MaterialAlphaMode.OPAQUE) { //glTF defaults to opaque
-                    glTFMaterial.alphaMode = alphaMode;
-                    if (alphaMode === MaterialAlphaMode.BLEND) {
-                        glTFMaterial.alphaCutoff = babylonPBRMetalRoughMaterial.alphaCutOff;
+                if (alphaMode) {
+                    if (alphaMode !== MaterialAlphaMode.OPAQUE) { //glTF defaults to opaque
+                        glTFMaterial.alphaMode = alphaMode;
+                        if (alphaMode === MaterialAlphaMode.BLEND) {
+                            glTFMaterial.alphaCutoff = babylonPBRMetalRoughMaterial.alphaCutOff;
+                        }
                     }
                     }
                 }
                 }
             }
             }
@@ -451,14 +460,14 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Converts an image typed array buffer to a base64 image.
-         * @param buffer - typed array buffer.
-         * @param width - width of the image.
-         * @param height - height of the image.
-         * @param mimeType - mimetype of the image.
-         * @returns - base64 image string.
+         * Converts an image typed array buffer to a base64 image
+         * @param buffer typed array buffer
+         * @param width width of the image
+         * @param height height of the image
+         * @param mimeType mimetype of the image
+         * @returns base64 image string
          */
          */
-        private static _CreateBase64FromCanvas(buffer: Uint8ClampedArray, width: number, height: number, mimeType: ImageMimeType): string {
+        private static _CreateBase64FromCanvas(buffer: Uint8ClampedArray | Float32Array, width: number, height: number, mimeType: ImageMimeType): string {
             const imageCanvas = document.createElement('canvas');
             const imageCanvas = document.createElement('canvas');
             imageCanvas.id = "WriteCanvas";
             imageCanvas.id = "WriteCanvas";
             const ctx = imageCanvas.getContext('2d') as CanvasRenderingContext2D;
             const ctx = imageCanvas.getContext('2d') as CanvasRenderingContext2D;
@@ -474,11 +483,11 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Generates a white texture based on the specified width and height.
-         * @param width - width of the texture in pixels.
-         * @param height - height of the texture in pixels.
-         * @param scene - babylonjs scene.
-         * @returns - white texture.
+         * Generates a white texture based on the specified width and height
+         * @param width width of the texture in pixels
+         * @param height height of the texture in pixels
+         * @param scene babylonjs scene
+         * @returns white texture
          */
          */
         private static _CreateWhiteTexture(width: number, height: number, scene: Scene): Texture {
         private static _CreateWhiteTexture(width: number, height: number, scene: Scene): Texture {
             const data = new Uint8Array(width * height * 4);
             const data = new Uint8Array(width * height * 4);
@@ -493,11 +502,11 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Resizes the two source textures to the same dimensions.  If a texture is null, a default white texture is generated.  If both textures are null, returns null.
-         * @param texture1 - first texture to resize.
-         * @param texture2 - second texture to resize.
-         * @param scene - babylonjs scene.
-         * @returns resized textures or null.
+         * Resizes the two source textures to the same dimensions.  If a texture is null, a default white texture is generated.  If both textures are null, returns null
+         * @param texture1 first texture to resize
+         * @param texture2 second texture to resize
+         * @param scene babylonjs scene
+         * @returns resized textures or null
          */
          */
         private static _ResizeTexturesToSameDimensions(texture1: BaseTexture, texture2: BaseTexture, scene: Scene): { "texture1": BaseTexture, "texture2": BaseTexture } {
         private static _ResizeTexturesToSameDimensions(texture1: BaseTexture, texture2: BaseTexture, scene: Scene): { "texture1": BaseTexture, "texture2": BaseTexture } {
             let texture1Size = texture1 ? texture1.getSize() : { width: 0, height: 0 };
             let texture1Size = texture1 ? texture1.getSize() : { width: 0, height: 0 };
@@ -535,14 +544,14 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Convert Specular Glossiness Textures to Metallic Roughness.
+         * Convert Specular Glossiness Textures to Metallic Roughness
          * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
          * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
          * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
          * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
-         * @param diffuseTexture - texture used to store diffuse information.
-         * @param specularGlossinessTexture - texture used to store specular and glossiness information.
-         * @param factors - specular glossiness material factors.
-         * @param mimeType - the mime type to use for the texture.
-         * @returns pbr metallic roughness interface or null.
+         * @param diffuseTexture texture used to store diffuse information
+         * @param specularGlossinessTexture texture used to store specular and glossiness information
+         * @param factors specular glossiness material factors
+         * @param mimeType the mime type to use for the texture
+         * @returns pbr metallic roughness interface or null
          */
          */
         private static _ConvertSpecularGlossinessTexturesToMetallicRoughness(diffuseTexture: BaseTexture, specularGlossinessTexture: BaseTexture, factors: _IPBRSpecularGlossiness, mimeType: ImageMimeType): Nullable<_IPBRMetallicRoughness> {
         private static _ConvertSpecularGlossinessTexturesToMetallicRoughness(diffuseTexture: BaseTexture, specularGlossinessTexture: BaseTexture, factors: _IPBRSpecularGlossiness, mimeType: ImageMimeType): Nullable<_IPBRMetallicRoughness> {
             if (!(diffuseTexture || specularGlossinessTexture)) {
             if (!(diffuseTexture || specularGlossinessTexture)) {
@@ -551,7 +560,8 @@ module BABYLON.GLTF2 {
 
 
             const scene = diffuseTexture ? diffuseTexture.getScene() : specularGlossinessTexture.getScene();
             const scene = diffuseTexture ? diffuseTexture.getScene() : specularGlossinessTexture.getScene();
             if (!scene) {
             if (!scene) {
-                throw new Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Scene from textures is missing!");
+                Tools.Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Scene from textures is missing!");
+                return null;
             }
             }
 
 
             const resizedTextures = this._ResizeTexturesToSameDimensions(diffuseTexture, specularGlossinessTexture, scene);
             const resizedTextures = this._ResizeTexturesToSameDimensions(diffuseTexture, specularGlossinessTexture, scene);
@@ -569,7 +579,8 @@ module BABYLON.GLTF2 {
                 diffuseBuffer = (resizedTextures.texture1.readPixels()) as Uint8Array;
                 diffuseBuffer = (resizedTextures.texture1.readPixels()) as Uint8Array;
             }
             }
             else {
             else {
-                throw new Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture1.name);
+                Tools.Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture1.name);
+                return null;
             }
             }
             pixels = resizedTextures.texture2.readPixels();
             pixels = resizedTextures.texture2.readPixels();
 
 
@@ -577,7 +588,8 @@ module BABYLON.GLTF2 {
                 specularGlossinessBuffer = (resizedTextures.texture2.readPixels()) as Uint8Array;
                 specularGlossinessBuffer = (resizedTextures.texture2.readPixels()) as Uint8Array;
             }
             }
             else {
             else {
-                throw new Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture2.name);
+                Tools.Error("_ConvertSpecularGlossinessTexturesToMetallicRoughness: Pixel array buffer type not supported for texture: " + resizedTextures.texture2.name);
+                return null;
             }
             }
 
 
             const byteLength = specularGlossinessBuffer.byteLength;
             const byteLength = specularGlossinessBuffer.byteLength;
@@ -675,9 +687,9 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Converts specular glossiness material properties to metallic roughness.
-         * @param specularGlossiness - interface with specular glossiness material properties.
-         * @returns - interface with metallic roughness material properties.
+         * Converts specular glossiness material properties to metallic roughness
+         * @param specularGlossiness interface with specular glossiness material properties
+         * @returns interface with metallic roughness material properties
          */
          */
         private static _ConvertSpecularGlossinessToMetallicRoughness(specularGlossiness: _IPBRSpecularGlossiness): _IPBRMetallicRoughness {
         private static _ConvertSpecularGlossinessToMetallicRoughness(specularGlossiness: _IPBRSpecularGlossiness): _IPBRMetallicRoughness {
             const diffusePerceivedBrightness = _GLTFMaterial._GetPerceivedBrightness(specularGlossiness.diffuseColor);
             const diffusePerceivedBrightness = _GLTFMaterial._GetPerceivedBrightness(specularGlossiness.diffuseColor);
@@ -699,9 +711,9 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Calculates the surface reflectance, independent of lighting conditions.
-         * @param color - Color source to calculate brightness from.
-         * @returns number representing the perceived brightness, or zero if color is undefined. 
+         * Calculates the surface reflectance, independent of lighting conditions
+         * @param color Color source to calculate brightness from
+         * @returns number representing the perceived brightness, or zero if color is undefined
          */
          */
         private static _GetPerceivedBrightness(color: Color3): number {
         private static _GetPerceivedBrightness(color: Color3): number {
             if (color) {
             if (color) {
@@ -711,9 +723,9 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Returns the maximum color component value.
+         * Returns the maximum color component value
          * @param color 
          * @param color 
-         * @returns maximum color component value, or zero if color is null or undefined.
+         * @returns maximum color component value, or zero if color is null or undefined
          */
          */
         private static _GetMaxComponent(color: Color3): number {
         private static _GetMaxComponent(color: Color3): number {
             if (color) {
             if (color) {
@@ -723,15 +735,15 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Convert a PBRMaterial (Metallic/Roughness) to Metallic Roughness factors.
-         * @param babylonPBRMaterial - BJS PBR Metallic Roughness Material.
-         * @param mimeType - mime type to use for the textures.
-         * @param images - array of glTF image interfaces.
-         * @param textures - array of glTF texture interfaces.
-         * @param glTFPbrMetallicRoughness - glTF PBR Metallic Roughness interface.
-         * @param imageData - map of image file name to data.
-         * @param hasTextureCoords - specifies if texture coordinates are present on the submesh to determine if textures should be applied.
-         * @returns - glTF PBR Metallic Roughness factors.
+         * Convert a PBRMaterial (Metallic/Roughness) to Metallic Roughness factors
+         * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
+         * @param mimeType mime type to use for the textures
+         * @param images array of glTF image interfaces
+         * @param textures array of glTF texture interfaces
+         * @param glTFPbrMetallicRoughness glTF PBR Metallic Roughness interface
+         * @param imageData map of image file name to data
+         * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
+         * @returns glTF PBR Metallic Roughness factors
          */
          */
         private static _ConvertMetalRoughFactorsToMetallicRoughness(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean): _IPBRMetallicRoughness {
         private static _ConvertMetalRoughFactorsToMetallicRoughness(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean): _IPBRMetallicRoughness {
             const metallicRoughness = {
             const metallicRoughness = {
@@ -758,24 +770,25 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Convert a PBRMaterial (Specular/Glossiness) to Metallic Roughness factors.
-         * @param babylonPBRMaterial - BJS PBR Metallic Roughness Material.
-         * @param mimeType - mime type to use for the textures.
-         * @param images - array of glTF image interfaces.
-         * @param textures - array of glTF texture interfaces.
-         * @param glTFPbrMetallicRoughness - glTF PBR Metallic Roughness interface.
-         * @param imageData - map of image file name to data.
-         * @param hasTextureCoords - specifies if texture coordinates are present on the submesh to determine if textures should be applied.
-         * @returns - glTF PBR Metallic Roughness factors.
+         * Convert a PBRMaterial (Specular/Glossiness) to Metallic Roughness factors
+         * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
+         * @param mimeType mime type to use for the textures
+         * @param images array of glTF image interfaces
+         * @param textures array of glTF texture interfaces
+         * @param glTFPbrMetallicRoughness glTF PBR Metallic Roughness interface
+         * @param imageData map of image file name to data
+         * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
+         * @returns glTF PBR Metallic Roughness factors
          */
          */
-        private static _ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean): _IPBRMetallicRoughness {
+        private static _ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean): Nullable<_IPBRMetallicRoughness> {
             const specGloss: _IPBRSpecularGlossiness = {
             const specGloss: _IPBRSpecularGlossiness = {
                 diffuseColor: babylonPBRMaterial.albedoColor || Color3.White(),
                 diffuseColor: babylonPBRMaterial.albedoColor || Color3.White(),
                 specularColor: babylonPBRMaterial.reflectivityColor || Color3.White(),
                 specularColor: babylonPBRMaterial.reflectivityColor || Color3.White(),
                 glossiness: babylonPBRMaterial.microSurface || 1,
                 glossiness: babylonPBRMaterial.microSurface || 1,
             };
             };
             if (babylonPBRMaterial.reflectivityTexture && !babylonPBRMaterial.useMicroSurfaceFromReflectivityMapAlpha) {
             if (babylonPBRMaterial.reflectivityTexture && !babylonPBRMaterial.useMicroSurfaceFromReflectivityMapAlpha) {
-                throw new Error("_ConvertPBRMaterial: Glossiness values not included in the reflectivity texture currently not supported");
+                Tools.Error("_ConvertPBRMaterial: Glossiness values not included in the reflectivity texture currently not supported");
+                return null;
             }
             }
 
 
             let metallicRoughnessFactors = this._ConvertSpecularGlossinessTexturesToMetallicRoughness(babylonPBRMaterial.albedoTexture, babylonPBRMaterial.reflectivityTexture, specGloss, mimeType);
             let metallicRoughnessFactors = this._ConvertSpecularGlossinessTexturesToMetallicRoughness(babylonPBRMaterial.albedoTexture, babylonPBRMaterial.reflectivityTexture, specGloss, mimeType);
@@ -803,14 +816,14 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Converts a Babylon PBR Metallic Roughness Material to a glTF Material.
-         * @param babylonPBRMaterial - BJS PBR Metallic Roughness Material.
-         * @param mimeType - mime type to use for the textures.
-         * @param images - array of glTF image interfaces.
-         * @param textures - array of glTF texture interfaces.
-         * @param materials - array of glTF material interfaces.
-         * @param imageData - map of image file name to data.
-         * @param hasTextureCoords - specifies if texture coordinates are present on the submesh to determine if textures should be applied.
+         * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
+         * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
+         * @param mimeType mime type to use for the textures
+         * @param images array of glTF image interfaces
+         * @param textures array of glTF texture interfaces
+         * @param materials array of glTF material interfaces
+         * @param imageData map of image file name to data
+         * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
          */
         public static _ConvertPBRMaterial(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean) {
         public static _ConvertPBRMaterial(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }, hasTextureCoords: boolean) {
             const glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness = {};
             const glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness = {};
@@ -826,83 +839,90 @@ module BABYLON.GLTF2 {
             else {
             else {
                 metallicRoughness = this._ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial, mimeType, images, textures, glTFPbrMetallicRoughness, imageData, hasTextureCoords);
                 metallicRoughness = this._ConvertSpecGlossFactorsToMetallicRoughness(babylonPBRMaterial, mimeType, images, textures, glTFPbrMetallicRoughness, imageData, hasTextureCoords);
             }
             }
+            if (metallicRoughness) {
+                if (!(this.FuzzyEquals(metallicRoughness.baseColor, Color3.White(), this._epsilon) && babylonPBRMaterial.alpha >= this._epsilon)) {
+                    glTFPbrMetallicRoughness.baseColorFactor = [
+                        metallicRoughness.baseColor.r,
+                        metallicRoughness.baseColor.g,
+                        metallicRoughness.baseColor.b,
+                        babylonPBRMaterial.alpha
+                    ];
+                }
 
 
-            if (!(this.FuzzyEquals(metallicRoughness.baseColor, Color3.White(), this._epsilon) && babylonPBRMaterial.alpha >= this._epsilon)) {
-                glTFPbrMetallicRoughness.baseColorFactor = [
-                    metallicRoughness.baseColor.r,
-                    metallicRoughness.baseColor.g,
-                    metallicRoughness.baseColor.b,
-                    babylonPBRMaterial.alpha
-                ];
-            }
-
-            if (metallicRoughness.metallic != null && metallicRoughness.metallic !== 1) {
-                glTFPbrMetallicRoughness.metallicFactor = metallicRoughness.metallic;
-            }
-            if (metallicRoughness.roughness != null && metallicRoughness.roughness !== 1) {
-                glTFPbrMetallicRoughness.roughnessFactor = metallicRoughness.roughness;
-            }
-
-            if (babylonPBRMaterial.backFaceCulling != null && !babylonPBRMaterial.backFaceCulling) {
-                if (!babylonPBRMaterial.twoSidedLighting) {
-                    Tools.Warn(babylonPBRMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
+                if (metallicRoughness.metallic != null && metallicRoughness.metallic !== 1) {
+                    glTFPbrMetallicRoughness.metallicFactor = metallicRoughness.metallic;
                 }
                 }
-                glTFMaterial.doubleSided = true;
-            }
-            if (hasTextureCoords) {
-                if (babylonPBRMaterial.bumpTexture) {
-                    const glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.bumpTexture, mimeType, images, textures, imageData);
-                    if (glTFTexture) {
-                        glTFMaterial.normalTexture = glTFTexture;
+                if (metallicRoughness.roughness != null && metallicRoughness.roughness !== 1) {
+                    glTFPbrMetallicRoughness.roughnessFactor = metallicRoughness.roughness;
+                }
+
+                if (babylonPBRMaterial.backFaceCulling != null && !babylonPBRMaterial.backFaceCulling) {
+                    if (!babylonPBRMaterial.twoSidedLighting) {
+                        Tools.Warn(babylonPBRMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
                     }
                     }
+                    glTFMaterial.doubleSided = true;
                 }
                 }
-                if (babylonPBRMaterial.ambientTexture) {
-                    const glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.ambientTexture, mimeType, images, textures, imageData);
-                    if (glTFTexture) {
-                        let occlusionTexture: IMaterialOcclusionTextureInfo = {
-                            index: glTFTexture.index
-                        };
+                if (hasTextureCoords) {
+                    if (babylonPBRMaterial.bumpTexture) {
+                        const glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.bumpTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture) {
+                            glTFMaterial.normalTexture = glTFTexture;
+                        }
+                    }
+                    if (babylonPBRMaterial.ambientTexture) {
+                        const glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.ambientTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture) {
+                            let occlusionTexture: IMaterialOcclusionTextureInfo = {
+                                index: glTFTexture.index
+                            };
 
 
-                        glTFMaterial.occlusionTexture = occlusionTexture;
+                            glTFMaterial.occlusionTexture = occlusionTexture;
 
 
-                        if (babylonPBRMaterial.ambientTextureStrength) {
-                            occlusionTexture.strength = babylonPBRMaterial.ambientTextureStrength;
+                            if (babylonPBRMaterial.ambientTextureStrength) {
+                                occlusionTexture.strength = babylonPBRMaterial.ambientTextureStrength;
+                            }
                         }
                         }
                     }
                     }
-                }
-                if (babylonPBRMaterial.emissiveTexture) {
-                    const glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.emissiveTexture, mimeType, images, textures, imageData);
-                    if (glTFTexture != null) {
-                        glTFMaterial.emissiveTexture = glTFTexture;
+                    if (babylonPBRMaterial.emissiveTexture) {
+                        const glTFTexture = _GLTFMaterial._ExportTexture(babylonPBRMaterial.emissiveTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture != null) {
+                            glTFMaterial.emissiveTexture = glTFTexture;
+                        }
                     }
                     }
-                }       
-            }
-            if (!this.FuzzyEquals(babylonPBRMaterial.emissiveColor, Color3.Black(), this._epsilon)) {
-                glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
-            }
-            if (babylonPBRMaterial.transparencyMode != null) {
-                const alphaMode = _GLTFMaterial._GetAlphaMode(babylonPBRMaterial);
-
-                if (alphaMode !== MaterialAlphaMode.OPAQUE) { //glTF defaults to opaque
-                    glTFMaterial.alphaMode = alphaMode;
-                    if (alphaMode === MaterialAlphaMode.BLEND) {
-                        glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
+                }
+                if (!this.FuzzyEquals(babylonPBRMaterial.emissiveColor, Color3.Black(), this._epsilon)) {
+                    glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
+                }
+                if (babylonPBRMaterial.transparencyMode != null) {
+                    const alphaMode = _GLTFMaterial._GetAlphaMode(babylonPBRMaterial);
+                    if (alphaMode) {
+                        if (alphaMode !== MaterialAlphaMode.OPAQUE) { //glTF defaults to opaque
+                            glTFMaterial.alphaMode = alphaMode;
+                            if (alphaMode === MaterialAlphaMode.BLEND) {
+                                glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
+                            }
+                        }
                     }
                     }
                 }
                 }
+
+                glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
+                materials.push(glTFMaterial);
             }
             }
+        }
 
 
-            glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
-            materials.push(glTFMaterial);
+        private static GetPixelsFromTexture(babylonTexture: Texture): Uint8Array | Float32Array {
+            let pixels = babylonTexture.textureType === Engine.TEXTURETYPE_UNSIGNED_INT ? babylonTexture.readPixels() as Uint8Array : babylonTexture.readPixels() as Float32Array;
+            return pixels;
         }
         }
 
 
         /**
         /**
-         * Extracts a texture from a Babylon texture into file data and glTF data.
-         * @param babylonTexture - Babylon texture to extract.
-         * @param mimeType - Mime Type of the babylonTexture.
-         * @param images - Array of glTF images.
-         * @param textures - Array of glTF textures.
-         * @param imageData - map of image file name and data.
-         * @return - glTF texture info, or null if the texture format is not supported.
+         * Extracts a texture from a Babylon texture into file data and glTF data
+         * @param babylonTexture Babylon texture to extract
+         * @param mimeType Mime Type of the babylonTexture
+         * @param images Array of glTF images
+         * @param textures Array of glTF textures
+         * @param imageData map of image file name and data
+         * @return glTF texture info, or null if the texture format is not supported
          */
          */
         private static _ExportTexture(babylonTexture: BaseTexture, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }): Nullable<ITextureInfo> {
         private static _ExportTexture(babylonTexture: BaseTexture, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }): Nullable<ITextureInfo> {
             let textureName = "texture_" + (textures.length - 1).toString();
             let textureName = "texture_" + (textures.length - 1).toString();
@@ -924,12 +944,13 @@ module BABYLON.GLTF2 {
                 extension = ".png";
                 extension = ".png";
             }
             }
             else {
             else {
-                throw new Error("Unsupported mime type " + mimeType);
+                Tools.Error("Unsupported mime type " + mimeType);
+                return null;
             }
             }
             textureName = baseFile + extension;
             textureName = baseFile + extension;
 
 
 
 
-            const pixels = babylonTexture.readPixels() as Uint8Array;
+            const pixels = _GLTFMaterial.GetPixelsFromTexture(babylonTexture as Texture);
 
 
             const size = babylonTexture.getSize();
             const size = babylonTexture.getSize();
 
 
@@ -939,14 +960,14 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Builds a texture from base64 string.
-         * @param base64Texture - base64 texture string.
-         * @param textureName - Name to use for the texture.
-         * @param mimeType - image mime type for the texture.
-         * @param images - array of images.
-         * @param textures - array of textures.
-         * @param imageData - map of image data.
-         * @returns - glTF texture info, or null if the texture format is not supported.
+         * Builds a texture from base64 string
+         * @param base64Texture base64 texture string
+         * @param textureName Name to use for the texture
+         * @param mimeType image mime type for the texture
+         * @param images array of images
+         * @param textures array of textures
+         * @param imageData map of image data
+         * @returns glTF texture info, or null if the texture format is not supported
          */
          */
         private static _GetTextureInfoFromBase64(base64Texture: string, textureName: string, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }): Nullable<ITextureInfo> {
         private static _GetTextureInfoFromBase64(base64Texture: string, textureName: string, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } }): Nullable<ITextureInfo> {
             let textureInfo: Nullable<ITextureInfo> = null;
             let textureInfo: Nullable<ITextureInfo> = null;
@@ -956,8 +977,9 @@ module BABYLON.GLTF2 {
             };
             };
 
 
             const binStr = atob(base64Texture.split(',')[1]);
             const binStr = atob(base64Texture.split(',')[1]);
-            const arr = new Uint8Array(binStr.length);
-            for (let i = 0; i < binStr.length; ++i) {
+            let arrBuff = new ArrayBuffer(binStr.length);
+            const arr = new Uint8Array(arrBuff);
+            for (let i = 0, length = binStr.length; i < length; ++i) {
                 arr[i] = binStr.charCodeAt(i);
                 arr[i] = binStr.charCodeAt(i);
             }
             }
             const imageValues = { data: arr, mimeType: mimeType };
             const imageValues = { data: arr, mimeType: mimeType };
@@ -967,7 +989,7 @@ module BABYLON.GLTF2 {
                 const glTFImage: IImage = {
                 const glTFImage: IImage = {
                     uri: textureName
                     uri: textureName
                 }
                 }
-                let foundIndex = -1;
+                let foundIndex: number = -1;
                 for (let i = 0; i < images.length; ++i) {
                 for (let i = 0; i < images.length; ++i) {
                     if (images[i].uri === textureName) {
                     if (images[i].uri === textureName) {
                         foundIndex = i;
                         foundIndex = i;

+ 23 - 18
serializers/src/glTF/2.0/babylon.glTFSerializer.ts

@@ -6,12 +6,15 @@ module BABYLON {
      */
      */
     export interface IExporterOptions {
     export interface IExporterOptions {
         /**
         /**
-         * Function which indicates whether a babylon mesh should be exported or not.
-         * @param mesh - source Babylon mesh. It is used to check whether it should be 
-         * exported to glTF or not.
+         * Function which indicates whether a babylon mesh should be exported or not
+         * @param mesh source Babylon mesh. It is used to check whether it should be exported to glTF or not
          * @returns boolean, which indicates whether the mesh should be exported (true) or not (false)
          * @returns boolean, which indicates whether the mesh should be exported (true) or not (false)
          */
          */
         shouldExportMesh?(mesh: AbstractMesh): boolean;
         shouldExportMesh?(mesh: AbstractMesh): boolean;
+        /**
+         * The sample rate to bake animation curves
+         */
+        animationSampleRate?: number;
     };
     };
 
 
     /**
     /**
@@ -19,39 +22,41 @@ module BABYLON {
      */
      */
     export class GLTF2Export {
     export class GLTF2Export {
         /**
         /**
-         * Exports the geometry of the scene to .gltf file format.
-         * @param scene - Babylon scene with scene hierarchy information.
-         * @param filePrefix - File prefix to use when generating the glTF file.
-         * @param options - Exporter options.
-         * @returns - Returns an object with a .gltf file and associates texture names
-         * as keys and their data and paths as values.
+         * Exports the geometry of the scene to .gltf file format
+         * @param scene Babylon scene with scene hierarchy information
+         * @param filePrefix File prefix to use when generating the glTF file
+         * @param options Exporter options
+         * @returns Returns an object with a .gltf file and associates texture names
+         * as keys and their data and paths as values
          */
          */
-        public static GLTF(scene: Scene, filePrefix: string, options?: IExporterOptions): _GLTFData {
+        public static GLTF(scene: Scene, filePrefix: string, options?: IExporterOptions): Nullable<GLTFData> {
             const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");
             const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");
             const gltfGenerator = new GLTF2._Exporter(scene, options);
             const gltfGenerator = new GLTF2._Exporter(scene, options);
             if (scene.isReady) {
             if (scene.isReady) {
                 return gltfGenerator._generateGLTF(glTFPrefix);
                 return gltfGenerator._generateGLTF(glTFPrefix);
             }
             }
             else {
             else {
-                throw new Error("glTF Serializer: Scene is not ready!");
+                Tools.Error("glTF Serializer: Scene is not ready!");
+                return null;
             } 
             } 
         }
         }
 
 
         /**
         /**
-         * Exports the geometry of the scene to .glb file format.
-         * @param scene - Babylon scene with scene hierarchy information.
-         * @param filePrefix - File prefix to use when generating glb file.
-         * @param options - Exporter options.
-         * @returns - Returns an object with a .glb filename as key and data as value
+         * Exports the geometry of the scene to .glb file format
+         * @param scene Babylon scene with scene hierarchy information
+         * @param filePrefix File prefix to use when generating glb file
+         * @param options Exporter options
+         * @returns Returns an object with a .glb filename as key and data as value
          */
          */
-        public static GLB(scene: Scene, filePrefix: string, options?: IExporterOptions): _GLTFData {
+        public static GLB(scene: Scene, filePrefix: string, options?: IExporterOptions): Nullable<GLTFData> {
             const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");        
             const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");        
             const gltfGenerator = new GLTF2._Exporter(scene, options);
             const gltfGenerator = new GLTF2._Exporter(scene, options);
             if (scene.isReady) {
             if (scene.isReady) {
                 return gltfGenerator._generateGLB(glTFPrefix);
                 return gltfGenerator._generateGLB(glTFPrefix);
             }
             }
             else {
             else {
-                throw new Error("glTF Serializer: Scene is not ready!");
+                Tools.Error("glTF Serializer: Scene is not ready!");
+                return null;
             }  
             }  
         }
         }
     }
     }

+ 135 - 0
serializers/src/glTF/2.0/babylon.glTFUtilities.ts

@@ -0,0 +1,135 @@
+/// <reference path="../../../../dist/babylon.glTF2Interface.d.ts"/>
+
+module BABYLON.GLTF2 {
+    /**
+     * @hidden
+     */
+    export class _GLTFUtilities {
+        /**
+         * Creates a buffer view based on the supplied arguments
+         * @param bufferIndex index value of the specified buffer
+         * @param byteOffset byte offset value
+         * @param byteLength byte length of the bufferView
+         * @param byteStride byte distance between conequential elements
+         * @param name name of the buffer view
+         * @returns bufferView for glTF
+         */
+        public static CreateBufferView(bufferIndex: number, byteOffset: number, byteLength: number, byteStride?: number, name?: string): IBufferView {
+            let bufferview: IBufferView = { buffer: bufferIndex, byteLength: byteLength };
+            if (byteOffset) {
+                bufferview.byteOffset = byteOffset;
+            }
+            if (name) {
+                bufferview.name = name;
+            }
+            if (byteStride) {
+                bufferview.byteStride = byteStride;
+            }
+
+            return bufferview;
+        }
+
+        /**
+         * Creates an accessor based on the supplied arguments
+         * @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 
+         */
+        public static CreateAccessor(bufferviewIndex: number, name: string, type: AccessorType, componentType: AccessorComponentType, count: number, byteOffset: Nullable<number>, min: Nullable<number[]>, max: Nullable<number[]>): IAccessor {
+            let accessor: IAccessor = { name: name, bufferView: bufferviewIndex, componentType: componentType, count: count, type: type };
+
+            if (min) {
+                accessor.min = min;
+            }
+            if (max) {
+                accessor.max = max;
+            }
+            if (byteOffset) {
+                accessor.byteOffset = byteOffset;
+            }
+
+            return accessor;
+        }
+
+        /**
+         * 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
+         * @returns min number array and max number array
+         */
+        public static CalculateMinMaxPositions(positions: FloatArray, vertexStart: number, vertexCount: number, convertToRightHandedSystem: boolean): { min: number[], max: number[] } {
+            const min = [Infinity, Infinity, Infinity];
+            const max = [-Infinity, -Infinity, -Infinity];
+            const positionStrideSize = 3;
+            let indexOffset: number;
+            let position: Vector3;
+            let vector: number[];
+
+            if (vertexCount) {
+                for (let i = vertexStart, length = vertexStart + vertexCount; i < length; ++i) {
+                    indexOffset = positionStrideSize * i;
+
+                    position = Vector3.FromArray(positions, indexOffset);
+                    if (convertToRightHandedSystem) {
+                        _GLTFUtilities.GetRightHandedVector3FromRef(position);
+                    }
+                    vector = position.asArray();
+
+                    for (let j = 0; j < positionStrideSize; ++j) {
+                        let num = vector[j];
+                        if (num < min[j]) {
+                            min[j] = num;
+                        }
+                        if (num > max[j]) {
+                            max[j] = num;
+                        }
+                        ++indexOffset;
+                    }
+                }
+            }
+            return { min, max };
+        }
+
+        /**
+         * Converts a new right-handed Vector3
+         * @param vector vector3 array
+         * @returns right-handed Vector3
+         */
+        public static GetRightHandedVector3(vector: Vector3): Vector3 {
+            return new Vector3(vector.x, vector.y, -vector.z);
+        }
+
+        /**
+         * Converts a Vector3 to right-handed
+         * @param vector Vector3 to convert to right-handed
+         */
+        public static GetRightHandedVector3FromRef(vector: Vector3) {
+            vector.z *= -1;
+        }
+
+        /**
+         * Converts a Vector4 to right-handed
+         * @param vector Vector4 to convert to right-handed
+         */
+        public static GetRightHandedVector4FromRef(vector: Vector4) {
+            vector.z *= -1;
+            vector.w *= -1;
+        }
+
+        /**
+         * Converts a Quaternion to right-handed
+         * @param quaternion Source quaternion to convert to right-handed
+         */
+        public static GetRightHandedQuaternionFromRef(quaternion: Quaternion) {
+            quaternion.x *= -1;
+            quaternion.y *= -1;
+        }
+    }
+}

+ 12 - 10
src/Actions/babylon.action.ts

@@ -11,7 +11,7 @@
 
 
         /**
         /**
          * Internal only - manager for action
          * Internal only - manager for action
-         * @ignore 
+         * @hidden 
          */
          */
         public _actionManager: ActionManager;
         public _actionManager: ActionManager;
 
 
@@ -30,7 +30,9 @@
          * @param triggerOptions the trigger, with or without parameters, for the action
          * @param triggerOptions the trigger, with or without parameters, for the action
          * @param condition an optional determinant of action 
          * @param condition an optional determinant of action 
          */
          */
-        constructor(public triggerOptions: any, condition?: Condition) {
+        constructor(
+            /** the trigger, with or without parameters, for the action */
+            public triggerOptions: any, condition?: Condition) {
 
 
             if (triggerOptions.parameter) {
             if (triggerOptions.parameter) {
                 this.trigger = triggerOptions.trigger;
                 this.trigger = triggerOptions.trigger;
@@ -45,7 +47,7 @@
 
 
         /**
         /**
          * Internal only
          * Internal only
-         * @ignore 
+         * @hidden 
          */
          */
         public _prepare(): void {
         public _prepare(): void {
         }
         }
@@ -60,7 +62,7 @@
 
 
         /**
         /**
          * Internal only - executes current action event
          * Internal only - executes current action event
-         * @ignore 
+         * @hidden 
          */
          */
         public _executeCurrent(evt?: ActionEvent): void {
         public _executeCurrent(evt?: ActionEvent): void {
             if (this._nextActiveAction._condition) {
             if (this._nextActiveAction._condition) {
@@ -116,7 +118,7 @@
 
 
         /**
         /**
          * Adds action to chain of actions, may be a DoNothingAction
          * Adds action to chain of actions, may be a DoNothingAction
-         * @param index The index of the attribute.
+         * @param action defines the next action to execute
          * @returns The action passed in
          * @returns The action passed in
          * @see https://www.babylonjs-playground.com/#1T30HR#0
          * @see https://www.babylonjs-playground.com/#1T30HR#0
          */
          */
@@ -131,7 +133,7 @@
 
 
         /**
         /**
          * Internal only
          * Internal only
-         * @ignore 
+         * @hidden 
          */
          */
         public _getProperty(propertyPath: string): string {
         public _getProperty(propertyPath: string): string {
             return this._actionManager._getProperty(propertyPath);
             return this._actionManager._getProperty(propertyPath);
@@ -139,7 +141,7 @@
 
 
         /**
         /**
          * Internal only
          * Internal only
-         * @ignore 
+         * @hidden 
          */
          */
         public _getEffectiveTarget(target: any, propertyPath: string): any {
         public _getEffectiveTarget(target: any, propertyPath: string): any {
             return this._actionManager._getEffectiveTarget(target, propertyPath);
             return this._actionManager._getEffectiveTarget(target, propertyPath);
@@ -155,7 +157,7 @@
         
         
         /**
         /**
          * Internal only called by serialize
          * Internal only called by serialize
-         * @ignore 
+         * @hidden 
          */
          */
         protected _serialize(serializedAction: any, parent?: any): any {
         protected _serialize(serializedAction: any, parent?: any): any {
             var serializationObject: any = { 
             var serializationObject: any = { 
@@ -189,7 +191,7 @@
         
         
         /**
         /**
          * Internal only
          * Internal only
-         * @ignore 
+         * @hidden 
          */
          */
         public static _SerializeValueAsString = (value: any): string => {
         public static _SerializeValueAsString = (value: any): string => {
             if (typeof value === "number") {
             if (typeof value === "number") {
@@ -219,7 +221,7 @@
         
         
         /**
         /**
          * Internal only
          * Internal only
-         * @ignore 
+         * @hidden 
          */
          */
         public static _GetTargetProperty = (target: Scene | Node) => {
         public static _GetTargetProperty = (target: Scene | Node) => {
             return {
             return {

+ 149 - 24
src/Actions/babylon.actionManager.ts

@@ -5,20 +5,36 @@
      */
      */
     export class ActionEvent {
     export class ActionEvent {
         /**
         /**
-         * @param source The mesh or sprite that triggered the action.
+         * Creates a new ActionEvent
+         * @param source The mesh or sprite that triggered the action
          * @param pointerX The X mouse cursor position at the time of the event
          * @param pointerX The X mouse cursor position at the time of the event
          * @param pointerY The Y mouse cursor position at the time of the event
          * @param pointerY The Y mouse cursor position at the time of the event
          * @param meshUnderPointer The mesh that is currently pointed at (can be null)
          * @param meshUnderPointer The mesh that is currently pointed at (can be null)
          * @param sourceEvent the original (browser) event that triggered the ActionEvent
          * @param sourceEvent the original (browser) event that triggered the ActionEvent
+         * @param additionalData additional data for the event
          */
          */
-        constructor(public source: any, public pointerX: number, public pointerY: number, public meshUnderPointer: Nullable<AbstractMesh>, public sourceEvent?: any, public additionalData?: any) {
+        constructor(
+            /** The mesh or sprite that triggered the action */
+            public source: any, 
+            /** The X mouse cursor position at the time of the event */
+            public pointerX: number, 
+            /** The Y mouse cursor position at the time of the event */
+            public pointerY: number, 
+            /** The mesh that is currently pointed at (can be null) */
+            public meshUnderPointer: Nullable<AbstractMesh>, 
+            /** the original (browser) event that triggered the ActionEvent */
+            public sourceEvent?: any, 
+            /** additional data for the event */
+            public additionalData?: any) {
 
 
         }
         }
 
 
         /**
         /**
          * Helper function to auto-create an ActionEvent from a source mesh.
          * Helper function to auto-create an ActionEvent from a source mesh.
          * @param source The source mesh that triggered the event
          * @param source The source mesh that triggered the event
-         * @param evt {Event} The original (browser) event
+         * @param evt The original (browser) event
+         * @param additionalData additional data for the event
+         * @returns the new ActionEvent
          */
          */
         public static CreateNew(source: AbstractMesh, evt?: Event, additionalData?: any): ActionEvent {
         public static CreateNew(source: AbstractMesh, evt?: Event, additionalData?: any): ActionEvent {
             var scene = source.getScene();
             var scene = source.getScene();
@@ -26,10 +42,12 @@
         }
         }
 
 
         /**
         /**
-         * Helper function to auto-create an ActionEvent from a source mesh.
+         * Helper function to auto-create an ActionEvent from a source sprite
          * @param source The source sprite that triggered the event
          * @param source The source sprite that triggered the event
          * @param scene Scene associated with the sprite
          * @param scene Scene associated with the sprite
-         * @param evt {Event} The original (browser) event
+         * @param evt The original (browser) event
+         * @param additionalData additional data for the event
+         * @returns the new ActionEvent
          */
          */
         public static CreateNewFromSprite(source: Sprite, scene: Scene, evt?: Event, additionalData?: any): ActionEvent {
         public static CreateNewFromSprite(source: Sprite, scene: Scene, evt?: Event, additionalData?: any): ActionEvent {
             return new ActionEvent(source, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt, additionalData);
             return new ActionEvent(source, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt, additionalData);
@@ -38,12 +56,21 @@
         /**
         /**
          * Helper function to auto-create an ActionEvent from a scene. If triggered by a mesh use ActionEvent.CreateNew
          * Helper function to auto-create an ActionEvent from a scene. If triggered by a mesh use ActionEvent.CreateNew
          * @param scene the scene where the event occurred
          * @param scene the scene where the event occurred
-         * @param evt {Event} The original (browser) event
+         * @param evt The original (browser) event
+         * @returns the new ActionEvent
          */
          */
         public static CreateNewFromScene(scene: Scene, evt: Event): ActionEvent {
         public static CreateNewFromScene(scene: Scene, evt: Event): ActionEvent {
             return new ActionEvent(null, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt);
             return new ActionEvent(null, scene.pointerX, scene.pointerY, scene.meshUnderPointer, evt);
         }
         }
 
 
+        /**
+         * Helper function to auto-create an ActionEvent from a primitive
+         * @param prim defines the target primitive
+         * @param pointerPos defines the pointer position
+         * @param evt The original (browser) event
+         * @param additionalData additional data for the event
+         * @returns the new ActionEvent
+         */
         public static CreateNewFromPrimitive(prim: any, pointerPos: Vector2, evt?: Event, additionalData?: any): ActionEvent {
         public static CreateNewFromPrimitive(prim: any, pointerPos: Vector2, evt?: Event, additionalData?: any): ActionEvent {
             return new ActionEvent(prim, pointerPos.x, pointerPos.y, null, evt, additionalData);
             return new ActionEvent(prim, pointerPos.x, pointerPos.y, null, evt, additionalData);
         }
         }
@@ -52,6 +79,7 @@
     /**
     /**
      * Action Manager manages all events to be triggered on a given mesh or the global scene.
      * Action Manager manages all events to be triggered on a given mesh or the global scene.
      * A single scene can have many Action Managers to handle predefined actions on specific meshes.
      * A single scene can have many Action Managers to handle predefined actions on specific meshes.
+     * @see http://doc.babylonjs.com/how_to/how_to_use_actions
      */
      */
     export class ActionManager {
     export class ActionManager {
         // Statics
         // Statics
@@ -73,84 +101,159 @@
         private static _OnKeyUpTrigger = 15;
         private static _OnKeyUpTrigger = 15;
         private static _OnPickOutTrigger = 16;
         private static _OnPickOutTrigger = 16;
 
 
+        /**
+         * Nothing
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get NothingTrigger(): number {
         public static get NothingTrigger(): number {
             return ActionManager._NothingTrigger;
             return ActionManager._NothingTrigger;
         }
         }
 
 
+        /** 
+         * On pick 
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnPickTrigger(): number {
         public static get OnPickTrigger(): number {
             return ActionManager._OnPickTrigger;
             return ActionManager._OnPickTrigger;
         }
         }
 
 
+        /** 
+         * On left pick
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnLeftPickTrigger(): number {
         public static get OnLeftPickTrigger(): number {
             return ActionManager._OnLeftPickTrigger;
             return ActionManager._OnLeftPickTrigger;
         }
         }
 
 
+        /** 
+         * On right pick
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnRightPickTrigger(): number {
         public static get OnRightPickTrigger(): number {
             return ActionManager._OnRightPickTrigger;
             return ActionManager._OnRightPickTrigger;
         }
         }
 
 
+        /** 
+         * On center pick 
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnCenterPickTrigger(): number {
         public static get OnCenterPickTrigger(): number {
             return ActionManager._OnCenterPickTrigger;
             return ActionManager._OnCenterPickTrigger;
         }
         }
 
 
+        /** 
+         * On pick down
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnPickDownTrigger(): number {
         public static get OnPickDownTrigger(): number {
             return ActionManager._OnPickDownTrigger;
             return ActionManager._OnPickDownTrigger;
         }
         }
 
 
+        /** 
+         * On double pick
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnDoublePickTrigger(): number {
         public static get OnDoublePickTrigger(): number {
             return ActionManager._OnDoublePickTrigger;
             return ActionManager._OnDoublePickTrigger;
         }
         }
 
 
+        /** 
+         * On pick up
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnPickUpTrigger(): number {
         public static get OnPickUpTrigger(): number {
             return ActionManager._OnPickUpTrigger;
             return ActionManager._OnPickUpTrigger;
         }
         }
 
 
-        /// This trigger will only be raised if you also declared a OnPickDown
+        /**
+         * On pick out.
+         * This trigger will only be raised if you also declared a OnPickDown
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnPickOutTrigger(): number {
         public static get OnPickOutTrigger(): number {
             return ActionManager._OnPickOutTrigger;
             return ActionManager._OnPickOutTrigger;
         }
         }
 
 
+        /** 
+         * On long press
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnLongPressTrigger(): number {
         public static get OnLongPressTrigger(): number {
             return ActionManager._OnLongPressTrigger;
             return ActionManager._OnLongPressTrigger;
         }
         }
 
 
+        /** 
+         * On pointer over
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnPointerOverTrigger(): number {
         public static get OnPointerOverTrigger(): number {
             return ActionManager._OnPointerOverTrigger;
             return ActionManager._OnPointerOverTrigger;
         }
         }
 
 
+        /** 
+         * On pointer out
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnPointerOutTrigger(): number {
         public static get OnPointerOutTrigger(): number {
             return ActionManager._OnPointerOutTrigger;
             return ActionManager._OnPointerOutTrigger;
         }
         }
 
 
+        /** 
+         * On every frame
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnEveryFrameTrigger(): number {
         public static get OnEveryFrameTrigger(): number {
             return ActionManager._OnEveryFrameTrigger;
             return ActionManager._OnEveryFrameTrigger;
         }
         }
 
 
+        /** 
+         * On intersection enter
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnIntersectionEnterTrigger(): number {
         public static get OnIntersectionEnterTrigger(): number {
             return ActionManager._OnIntersectionEnterTrigger;
             return ActionManager._OnIntersectionEnterTrigger;
         }
         }
 
 
+        /** 
+         * On intersection exit
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnIntersectionExitTrigger(): number {
         public static get OnIntersectionExitTrigger(): number {
             return ActionManager._OnIntersectionExitTrigger;
             return ActionManager._OnIntersectionExitTrigger;
         }
         }
 
 
+        /**
+         * On key down
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnKeyDownTrigger(): number {
         public static get OnKeyDownTrigger(): number {
             return ActionManager._OnKeyDownTrigger;
             return ActionManager._OnKeyDownTrigger;
         }
         }
 
 
+        /**
+         * On key up
+         * @see http://doc.babylonjs.com/how_to/how_to_use_actions#triggers
+         */
         public static get OnKeyUpTrigger(): number {
         public static get OnKeyUpTrigger(): number {
             return ActionManager._OnKeyUpTrigger;
             return ActionManager._OnKeyUpTrigger;
         }
         }
 
 
+        /** Gets the list of active triggers */
         public static Triggers: { [key: string]: number } = {};
         public static Triggers: { [key: string]: number } = {};
 
 
         // Members
         // Members
+        /** Gets the list of actions */
         public actions = new Array<Action>();
         public actions = new Array<Action>();
 
 
+        /** Gets the cursor to use when hovering items */
         public hoverCursor: string = '';
         public hoverCursor: string = '';
 
 
         private _scene: Scene;
         private _scene: Scene;
 
 
+        /**
+         * Creates a new action manager
+         * @param scene defines the hosting scene
+         */
         constructor(scene: Scene) {
         constructor(scene: Scene) {
             this._scene = scene || Engine.LastCreatedScene;
             this._scene = scene || Engine.LastCreatedScene;
 
 
@@ -158,6 +261,10 @@
         }
         }
 
 
         // Methods
         // Methods
+
+        /**
+         * Releases all associated resources
+         */
         public dispose(): void {
         public dispose(): void {
             var index = this._scene._actionManagers.indexOf(this);
             var index = this._scene._actionManagers.indexOf(this);
 
 
@@ -174,14 +281,18 @@
             }
             }
         }
         }
 
 
+        /** 
+         * Gets hosting scene 
+         * @returns the hosting scene
+         */
         public getScene(): Scene {
         public getScene(): Scene {
             return this._scene;
             return this._scene;
         }
         }
 
 
         /**
         /**
          * Does this action manager handles actions of any of the given triggers
          * Does this action manager handles actions of any of the given triggers
-         * @param {number[]} triggers - the triggers to be tested
-         * @return {boolean} whether one (or more) of the triggers is handeled 
+         * @param triggers defines the triggers to be tested
+         * @return a boolean indicating whether one (or more) of the triggers is handled 
          */
          */
         public hasSpecificTriggers(triggers: number[]): boolean {
         public hasSpecificTriggers(triggers: number[]): boolean {
             for (var index = 0; index < this.actions.length; index++) {
             for (var index = 0; index < this.actions.length; index++) {
@@ -221,7 +332,6 @@
 
 
         /**
         /**
          * Does this action manager has pointer triggers
          * Does this action manager has pointer triggers
-         * @return {boolean} whether or not it has pointer triggers
          */
          */
         public get hasPointerTriggers(): boolean {
         public get hasPointerTriggers(): boolean {
             for (var index = 0; index < this.actions.length; index++) {
             for (var index = 0; index < this.actions.length; index++) {
@@ -237,7 +347,6 @@
 
 
         /**
         /**
          * Does this action manager has pick triggers
          * Does this action manager has pick triggers
-         * @return {boolean} whether or not it has pick triggers
          */
          */
         public get hasPickTriggers(): boolean {
         public get hasPickTriggers(): boolean {
             for (var index = 0; index < this.actions.length; index++) {
             for (var index = 0; index < this.actions.length; index++) {
@@ -253,8 +362,7 @@
 
 
         /**
         /**
          * Does exist one action manager with at least one trigger 
          * Does exist one action manager with at least one trigger 
-         * @return {boolean} whether or not it exists one action manager with one trigger
-        **/
+         **/
         public static get HasTriggers(): boolean {
         public static get HasTriggers(): boolean {
             for (var t in ActionManager.Triggers) {
             for (var t in ActionManager.Triggers) {
                 if (ActionManager.Triggers.hasOwnProperty(t)) {
                 if (ActionManager.Triggers.hasOwnProperty(t)) {
@@ -266,8 +374,7 @@
 
 
         /**
         /**
          * Does exist one action manager with at least one pick trigger 
          * Does exist one action manager with at least one pick trigger 
-         * @return {boolean} whether or not it exists one action manager with one pick trigger
-        **/
+         **/
         public static get HasPickTriggers(): boolean {
         public static get HasPickTriggers(): boolean {
             for (var t in ActionManager.Triggers) {
             for (var t in ActionManager.Triggers) {
                 if (ActionManager.Triggers.hasOwnProperty(t)) {
                 if (ActionManager.Triggers.hasOwnProperty(t)) {
@@ -282,8 +389,8 @@
 
 
         /**
         /**
          * Does exist one action manager that handles actions of a given trigger
          * Does exist one action manager that handles actions of a given trigger
-         * @param {number} trigger - the trigger to be tested
-         * @return {boolean} whether the trigger is handeled by at least one action manager
+         * @param trigger defines the trigger to be tested
+         * @return a boolean indicating whether the trigger is handeled by at least one action manager
         **/
         **/
         public static HasSpecificTrigger(trigger: number): boolean {
         public static HasSpecificTrigger(trigger: number): boolean {
             for (var t in ActionManager.Triggers) {
             for (var t in ActionManager.Triggers) {
@@ -299,8 +406,8 @@
 
 
         /**
         /**
          * Registers an action to this action manager
          * Registers an action to this action manager
-         * @param {BABYLON.Action} action - the action to be registered
-         * @return {BABYLON.Action} the action amended (prepared) after registration
+         * @param action defines the action to be registered
+         * @return the action amended (prepared) after registration
          */
          */
         public registerAction(action: Action): Nullable<Action> {
         public registerAction(action: Action): Nullable<Action> {
             if (action.trigger === ActionManager.OnEveryFrameTrigger) {
             if (action.trigger === ActionManager.OnEveryFrameTrigger) {
@@ -327,8 +434,8 @@
 
 
         /**
         /**
          * Unregisters an action to this action manager
          * Unregisters an action to this action manager
-         * @param action The action to be unregistered
-         * @return whether the action has been unregistered
+         * @param action defines the action to be unregistered
+         * @return a boolean indicating whether the action has been unregistered
          */
          */
         public unregisterAction(action: Action): Boolean {
         public unregisterAction(action: Action): Boolean {
             var index = this.actions.indexOf(action);
             var index = this.actions.indexOf(action);
@@ -346,8 +453,8 @@
 
 
         /**
         /**
          * Process a specific trigger
          * Process a specific trigger
-         * @param {number} trigger - the trigger to process
-         * @param evt {BABYLON.ActionEvent} the event details to be processed
+         * @param trigger defines the trigger to process
+         * @param evt defines the event details to be processed
          */
          */
         public processTrigger(trigger: number, evt?: ActionEvent): void {
         public processTrigger(trigger: number, evt?: ActionEvent): void {
             for (var index = 0; index < this.actions.length; index++) {
             for (var index = 0; index < this.actions.length; index++) {
@@ -381,6 +488,7 @@
             }
             }
         }
         }
 
 
+        /** @hidden */
         public _getEffectiveTarget(target: any, propertyPath: string): any {
         public _getEffectiveTarget(target: any, propertyPath: string): any {
             var properties = propertyPath.split(".");
             var properties = propertyPath.split(".");
 
 
@@ -391,12 +499,18 @@
             return target;
             return target;
         }
         }
 
 
+        /** @hidden */
         public _getProperty(propertyPath: string): string {
         public _getProperty(propertyPath: string): string {
             var properties = propertyPath.split(".");
             var properties = propertyPath.split(".");
 
 
             return properties[properties.length - 1];
             return properties[properties.length - 1];
         }
         }
 
 
+        /**
+         * Serialize this manager to a JSON object
+         * @param name defines the property name to store this manager
+         * @returns a JSON representation of this manager
+         */
         public serialize(name: string): any {
         public serialize(name: string): any {
             var root = {
             var root = {
                 children: new Array(),
                 children: new Array(),
@@ -441,7 +555,13 @@
             return root;
             return root;
         }
         }
 
 
-        public static Parse(parsedActions: any, object: Nullable<AbstractMesh>, scene: Scene) {
+        /**
+         * Creates a new ActionManager from a JSON data
+         * @param parsedActions defines the JSON data to read from
+         * @param object defines the hosting mesh
+         * @param scene defines the hosting scene
+         */
+        public static Parse(parsedActions: any, object: Nullable<AbstractMesh>, scene: Scene): void {
             var actionManager = new ActionManager(scene);
             var actionManager = new ActionManager(scene);
             if (object === null)
             if (object === null)
                 scene.actionManager = actionManager;
                 scene.actionManager = actionManager;
@@ -626,6 +746,11 @@
             }
             }
         }
         }
 
 
+        /**
+         * Get a trigger name by index
+         * @param trigger defines the trigger index
+         * @returns a trigger name
+         */
         public static GetTriggerName(trigger: number): string {
         public static GetTriggerName(trigger: number): string {
             switch (trigger) {
             switch (trigger) {
                 case 0: return "NothingTrigger";
                 case 0: return "NothingTrigger";

+ 17 - 17
src/Actions/babylon.condition.ts

@@ -5,19 +5,19 @@
     export class Condition {
     export class Condition {
         /**
         /**
          * Internal only - manager for action
          * Internal only - manager for action
-         * @ignore 
+         * @hidden 
          */
          */
         public _actionManager: ActionManager;
         public _actionManager: ActionManager;
 
 
         /**
         /**
          * Internal only
          * Internal only
-         * @ignore 
+         * @hidden 
          */
          */
         public _evaluationId: number;
         public _evaluationId: number;
 
 
         /**
         /**
          * Internal only
          * Internal only
-         * @ignore 
+         * @hidden 
          */
          */
         public _currentResult: boolean;
         public _currentResult: boolean;
 
 
@@ -39,7 +39,7 @@
 
 
         /**
         /**
          * Internal only 
          * Internal only 
-         * @ignore 
+         * @hidden 
          */
          */
         public _getProperty(propertyPath: string): string {
         public _getProperty(propertyPath: string): string {
             return this._actionManager._getProperty(propertyPath);
             return this._actionManager._getProperty(propertyPath);
@@ -47,7 +47,7 @@
 
 
         /**
         /**
          * Internal only 
          * Internal only 
-         * @ignore 
+         * @hidden 
          */
          */
         public _getEffectiveTarget(target: any, propertyPath: string): any {
         public _getEffectiveTarget(target: any, propertyPath: string): any {
             return this._actionManager._getEffectiveTarget(target, propertyPath);
             return this._actionManager._getEffectiveTarget(target, propertyPath);
@@ -62,7 +62,7 @@
         
         
         /**
         /**
          * Internal only 
          * Internal only 
-         * @ignore 
+         * @hidden 
          */
          */
         protected _serialize(serializedCondition: any): any {
         protected _serialize(serializedCondition: any): any {
             return { 
             return { 
@@ -81,25 +81,25 @@
         
         
         /**
         /**
          * Internal only 
          * Internal only 
-         * @ignore 
+         * @hidden 
          */
          */
         private static _IsEqual = 0;
         private static _IsEqual = 0;
 
 
         /**
         /**
          * Internal only 
          * Internal only 
-         * @ignore 
+         * @hidden 
          */
          */
         private static _IsDifferent = 1;
         private static _IsDifferent = 1;
 
 
         /**
         /**
          * Internal only 
          * Internal only 
-         * @ignore 
+         * @hidden 
          */
          */
         private static _IsGreater = 2;
         private static _IsGreater = 2;
 
 
         /**
         /**
          * Internal only 
          * Internal only 
-         * @ignore 
+         * @hidden 
          */
          */
         private static _IsLesser = 3;
         private static _IsLesser = 3;
 
 
@@ -133,25 +133,25 @@
 
 
         /**
         /**
          * Internal only The action manager for the condition
          * Internal only The action manager for the condition
-         * @ignore 
+         * @hidden 
          */
          */
         public _actionManager: ActionManager;
         public _actionManager: ActionManager;
 
 
         /**
         /**
          * Internal only 
          * Internal only 
-         * @ignore 
+         * @hidden 
          */
          */
         private _target: any;
         private _target: any;
 
 
         /**
         /**
          * Internal only 
          * Internal only 
-         * @ignore 
+         * @hidden 
          */
          */
         private _effectiveTarget: any;
         private _effectiveTarget: any;
 
 
         /**
         /**
          * Internal only 
          * Internal only 
-         * @ignore 
+         * @hidden 
          */
          */
         private _property: string;
         private _property: string;
 
 
@@ -241,7 +241,7 @@
         
         
         /**
         /**
          * Internal only - manager for action
          * Internal only - manager for action
-         * @ignore 
+         * @hidden 
          */
          */
         public _actionManager: ActionManager;
         public _actionManager: ActionManager;
 
 
@@ -272,13 +272,13 @@
         
         
         /**
         /**
          * Internal only - manager for action
          * Internal only - manager for action
-         * @ignore 
+         * @hidden 
          */
          */
         public _actionManager: ActionManager;
         public _actionManager: ActionManager;
 
 
         /**
         /**
          * Internal only
          * Internal only
-         * @ignore 
+         * @hidden 
          */
          */
         private _target: any;
         private _target: any;
 
 

+ 5 - 6
src/Animations/babylon.animation.ts

@@ -226,7 +226,7 @@
         private _easingFunction: IEasingFunction;
         private _easingFunction: IEasingFunction;
 
 
         /**
         /**
-         * @ignore Internal use only
+         * @hidden Internal use only
          */
          */
         public _runtimeAnimations = new Array<RuntimeAnimation>();
         public _runtimeAnimations = new Array<RuntimeAnimation>();
 
 
@@ -251,7 +251,7 @@
         private _ranges: { [name: string]: Nullable<AnimationRange> } = {};
         private _ranges: { [name: string]: Nullable<AnimationRange> } = {};
 
 
         /**
         /**
-         * @ignore Internal use
+         * @hidden Internal use
          */
          */
         public static _PrepareAnimation(name: string, targetProperty: string, framePerSecond: number, totalFrame: number,
         public static _PrepareAnimation(name: string, targetProperty: string, framePerSecond: number, totalFrame: number,
             from: any, to: any, loopMode?: number, easingFunction?: EasingFunction): Nullable<Animation> {
             from: any, to: any, loopMode?: number, easingFunction?: EasingFunction): Nullable<Animation> {
@@ -744,7 +744,7 @@
         }
         }
 
 
         /**
         /**
-         * @ignore Internal use only
+         * @hidden Internal use only
          */
          */
         public _getKeyValue(value: any): any {
         public _getKeyValue(value: any): any {
             if (typeof value === "function") {
             if (typeof value === "function") {
@@ -755,7 +755,7 @@
         } 
         } 
 
 
         /**
         /**
-         * @ignore Internal use only
+         * @hidden Internal use only
          */
          */
         public _interpolate(currentFrame: number, repeatCount: number, workValue?: any, loopMode?: number, offsetValue?: any, highLimitValue?: any): any {
         public _interpolate(currentFrame: number, repeatCount: number, workValue?: any, loopMode?: number, offsetValue?: any, highLimitValue?: any): any {
             if (loopMode === Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) {
             if (loopMode === Animation.ANIMATIONLOOPMODE_CONSTANT && repeatCount > 0) {
@@ -866,8 +866,7 @@
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
                                     if (Animation.AllowMatricesInterpolation) {
                                     if (Animation.AllowMatricesInterpolation) {
-                                        workValue = this.matrixInterpolateFunction(startValue, endValue, gradient, workValue);
-                                        return workValue;
+                                        return this.matrixInterpolateFunction(startValue, endValue, gradient, workValue);
                                     }
                                     }
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
                                     return startValue;
                                     return startValue;

+ 7 - 2
src/Animations/babylon.runtimeAnimation.ts

@@ -64,7 +64,7 @@
          */
          */
         private _currentValue: any;
         private _currentValue: any;
         
         
-        /** @ignore */
+        /** @hidden */
         public _workValue: any;
         public _workValue: any;
         
         
         /**
         /**
@@ -203,6 +203,11 @@
          */
          */
         private _interpolate(currentFrame: number, repeatCount: number, loopMode?: number, offsetValue?: any, highLimitValue?: any): any {
         private _interpolate(currentFrame: number, repeatCount: number, loopMode?: number, offsetValue?: any, highLimitValue?: any): any {
             this._currentFrame = currentFrame;
             this._currentFrame = currentFrame;
+
+            if (this._animation.dataType === Animation.ANIMATIONTYPE_MATRIX && !this._workValue) {
+                this._workValue = Matrix.Zero();
+            }
+
             return this._animation._interpolate(currentFrame, repeatCount, this._workValue, loopMode, offsetValue, highLimitValue);
             return this._animation._interpolate(currentFrame, repeatCount, this._workValue, loopMode, offsetValue, highLimitValue);
         }
         }
 
 
@@ -361,7 +366,7 @@
         }
         }
 
 
         /**
         /**
-         * @ignore Internal use only
+         * @hidden Internal use only
          */
          */
         public _prepareForSpeedRatioChange(newSpeedRatio: number): void {
         public _prepareForSpeedRatioChange(newSpeedRatio: number): void {
             let newRatio = this._previousDelay * (this._animation.framePerSecond * newSpeedRatio) / 1000.0;
             let newRatio = this._previousDelay * (this._animation.framePerSecond * newSpeedRatio) / 1000.0;

+ 63 - 1
src/Audio/babylon.analyser.ts

@@ -1,9 +1,33 @@
 module BABYLON {
 module BABYLON {
+    /**
+     * Class used to work with sound analyzer using fast fourier transform (FFT)
+     * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music
+     */
     export class Analyser {
     export class Analyser {
+        /**
+         * Gets or sets the smoothing
+         * @ignorenaming
+         */
         public SMOOTHING = 0.75;
         public SMOOTHING = 0.75;
+        /**
+         * Gets or sets the FFT table size
+         * @ignorenaming
+         */
         public FFT_SIZE = 512;
         public FFT_SIZE = 512;
+        /**
+         * Gets or sets the bar graph amplitude
+         * @ignorenaming
+         */
         public BARGRAPHAMPLITUDE = 256;
         public BARGRAPHAMPLITUDE = 256;
+        /**
+         * Gets or sets the position of the debug canvas
+         * @ignorenaming
+         */
         public DEBUGCANVASPOS = { x: 20, y: 20 };
         public DEBUGCANVASPOS = { x: 20, y: 20 };
+        /**
+         * Gets or sets the debug canvas size
+         * @ignorenaming
+         */
         public DEBUGCANVASSIZE = { width: 320, height: 200 }
         public DEBUGCANVASSIZE = { width: 320, height: 200 }
 
 
         private _byteFreqs: Uint8Array;
         private _byteFreqs: Uint8Array;
@@ -16,6 +40,10 @@ module BABYLON {
         private _registerFunc: Nullable<() => void>;
         private _registerFunc: Nullable<() => void>;
         private _audioEngine: AudioEngine;
         private _audioEngine: AudioEngine;
 
 
+        /**
+         * Creates a new analyser
+         * @param scene defines hosting scene
+         */
         constructor(scene: Scene) {
         constructor(scene: Scene) {
             this._scene = scene;
             this._scene = scene;
             this._audioEngine = Engine.audioEngine;
             this._audioEngine = Engine.audioEngine;
@@ -29,6 +57,11 @@ module BABYLON {
             }
             }
         }
         }
 
 
+        /**
+         * Get the number of data values you will have to play with for the visualization
+         * @see https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/frequencyBinCount
+         * @returns a number
+         */
         public getFrequencyBinCount(): number {
         public getFrequencyBinCount(): number {
             if (this._audioEngine.canUseWebAudio) {
             if (this._audioEngine.canUseWebAudio) {
                 return this._webAudioAnalyser.frequencyBinCount;
                 return this._webAudioAnalyser.frequencyBinCount;
@@ -38,6 +71,11 @@ module BABYLON {
             }
             }
         }
         }
 
 
+        /**
+         * Gets the current frequency data as a byte array
+         * @see https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getByteFrequencyData
+         * @returns a Uint8Array
+         */
         public getByteFrequencyData(): Uint8Array {
         public getByteFrequencyData(): Uint8Array {
             if (this._audioEngine.canUseWebAudio) {
             if (this._audioEngine.canUseWebAudio) {
                 this._webAudioAnalyser.smoothingTimeConstant = this.SMOOTHING;
                 this._webAudioAnalyser.smoothingTimeConstant = this.SMOOTHING;
@@ -47,6 +85,11 @@ module BABYLON {
             return this._byteFreqs;
             return this._byteFreqs;
         }
         }
 
 
+        /**
+         * Gets the current waveform as a byte array
+         * @see https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getByteTimeDomainData
+         * @returns a Uint8Array
+         */
         public getByteTimeDomainData(): Uint8Array {
         public getByteTimeDomainData(): Uint8Array {
             if (this._audioEngine.canUseWebAudio) {
             if (this._audioEngine.canUseWebAudio) {
                 this._webAudioAnalyser.smoothingTimeConstant = this.SMOOTHING;
                 this._webAudioAnalyser.smoothingTimeConstant = this.SMOOTHING;
@@ -56,7 +99,12 @@ module BABYLON {
             return this._byteTime;
             return this._byteTime;
         }
         }
 
 
-        public getFloatFrequencyData(): Uint8Array {
+        /**
+         * Gets the current frequency data as a float array
+         * @see https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getByteFrequencyData
+         * @returns a Float32Array
+         */        
+        public getFloatFrequencyData(): Float32Array {
             if (this._audioEngine.canUseWebAudio) {
             if (this._audioEngine.canUseWebAudio) {
                 this._webAudioAnalyser.smoothingTimeConstant = this.SMOOTHING;
                 this._webAudioAnalyser.smoothingTimeConstant = this.SMOOTHING;
                 this._webAudioAnalyser.fftSize = this.FFT_SIZE;
                 this._webAudioAnalyser.fftSize = this.FFT_SIZE;
@@ -65,6 +113,9 @@ module BABYLON {
             return this._floatFreqs;
             return this._floatFreqs;
         }
         }
 
 
+        /**
+         * Renders the debug canvas
+         */
         public drawDebugCanvas() {
         public drawDebugCanvas() {
             if (this._audioEngine.canUseWebAudio) {
             if (this._audioEngine.canUseWebAudio) {
                 if (!this._debugCanvas) {
                 if (!this._debugCanvas) {
@@ -102,6 +153,9 @@ module BABYLON {
             }
             }
         }
         }
 
 
+        /**
+         * Stops rendering the debug canvas and removes it
+         */
         public stopDebugCanvas() {
         public stopDebugCanvas() {
             if (this._debugCanvas) {
             if (this._debugCanvas) {
                 if (this._registerFunc) {
                 if (this._registerFunc) {
@@ -114,6 +168,11 @@ module BABYLON {
             }
             }
         }
         }
 
 
+        /**
+         * Connects two audio nodes
+         * @param inputAudioNode defines first node to connect
+         * @param outputAudioNode defines second node to connect
+         */
         public connectAudioNodes(inputAudioNode: AudioNode, outputAudioNode: AudioNode) {
         public connectAudioNodes(inputAudioNode: AudioNode, outputAudioNode: AudioNode) {
             if (this._audioEngine.canUseWebAudio) {
             if (this._audioEngine.canUseWebAudio) {
                 inputAudioNode.connect(this._webAudioAnalyser);
                 inputAudioNode.connect(this._webAudioAnalyser);
@@ -121,6 +180,9 @@ module BABYLON {
             }
             }
         }
         }
 
 
+        /**
+         * Releases all associated resources
+         */
         public dispose() {
         public dispose() {
             if (this._audioEngine.canUseWebAudio) {
             if (this._audioEngine.canUseWebAudio) {
                 this._webAudioAnalyser.disconnect();
                 this._webAudioAnalyser.disconnect();

+ 4 - 4
src/Bones/babylon.bone.ts

@@ -23,7 +23,7 @@
         public length: number;
         public length: number;
 
 
         /** 
         /** 
-         * @ignore Internal only
+         * @hidden Internal only
          * Set this value to map this bone to a different index in the transform matrices
          * Set this value to map this bone to a different index in the transform matrices
          * Set this value to -1 to exclude the bone from the transform matrices
          * Set this value to -1 to exclude the bone from the transform matrices
          */
          */
@@ -45,13 +45,13 @@
         private _needToDecompose = true;
         private _needToDecompose = true;
         private _needToCompose = false;
         private _needToCompose = false;
 
 
-        /** @ignore */
+        /** @hidden */
         get _matrix(): Matrix {
         get _matrix(): Matrix {
             this._compose();
             this._compose();
             return this._localMatrix;
             return this._localMatrix;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         set _matrix(value: Matrix) {
         set _matrix(value: Matrix) {
             this._localMatrix.copyFrom(value);
             this._localMatrix.copyFrom(value);
             this._needToDecompose = true;
             this._needToDecompose = true;
@@ -290,7 +290,7 @@
             }
             }
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _updateDifferenceMatrix(rootMatrix?: Matrix, updateChildren = true): void {
         public _updateDifferenceMatrix(rootMatrix?: Matrix, updateChildren = true): void {
             if (!rootMatrix) {
             if (!rootMatrix) {
                 rootMatrix = this._baseMatrix;
                 rootMatrix = this._baseMatrix;

+ 4 - 4
src/Bones/babylon.skeleton.ts

@@ -293,17 +293,17 @@
             return this._scene.beginAnimation(this, range.from, range.to, loop, speedRatio, onAnimationEnd);
             return this._scene.beginAnimation(this, range.from, range.to, loop, speedRatio, onAnimationEnd);
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _markAsDirty(): void {
         public _markAsDirty(): void {
             this._isDirty = true;
             this._isDirty = true;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _registerMeshWithPoseMatrix(mesh: AbstractMesh): void {
         public _registerMeshWithPoseMatrix(mesh: AbstractMesh): void {
             this._meshesWithPoseMatrix.push(mesh);
             this._meshesWithPoseMatrix.push(mesh);
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _unregisterMeshWithPoseMatrix(mesh: AbstractMesh): void {
         public _unregisterMeshWithPoseMatrix(mesh: AbstractMesh): void {
             var index = this._meshesWithPoseMatrix.indexOf(mesh);
             var index = this._meshesWithPoseMatrix.indexOf(mesh);
 
 
@@ -312,7 +312,7 @@
             }
             }
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _computeTransformMatrices(targetMatrix: Float32Array, initialSkinMatrix: Nullable<Matrix>): void {
         public _computeTransformMatrices(targetMatrix: Float32Array, initialSkinMatrix: Nullable<Matrix>): void {
 
 
             this.onBeforeComputeObservable.notifyObservers(this);
             this.onBeforeComputeObservable.notifyObservers(this);

+ 8 - 14
src/Cameras/Inputs/babylon.freeCameraMouseInput.ts

@@ -74,14 +74,11 @@ module BABYLON {
                         }
                         }
 
 
                         var offsetX = evt.clientX - this.previousPosition.x;
                         var offsetX = evt.clientX - this.previousPosition.x;
-                        var offsetY = evt.clientY - this.previousPosition.y;
-
-                        if (this.camera.getScene().useRightHandedSystem) {
-                            this.camera.cameraRotation.y -= offsetX / this.angularSensibility;
-                        } else {
-                            this.camera.cameraRotation.y += offsetX / this.angularSensibility;
-                        }
+                        if (this.camera.getScene().useRightHandedSystem) offsetX *= -1;
+                        if (this.camera.parent && this.camera.parent._getWorldMatrixDeterminant() < 0) offsetX *= -1;
+                        this.camera.cameraRotation.y += offsetX / this.angularSensibility;
 
 
+                        var offsetY = evt.clientY - this.previousPosition.y;
                         this.camera.cameraRotation.x += offsetY / this.angularSensibility;
                         this.camera.cameraRotation.x += offsetY / this.angularSensibility;
 
 
                         this.previousPosition = {
                         this.previousPosition = {
@@ -106,14 +103,11 @@ module BABYLON {
                 }
                 }
 
 
                 var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
                 var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
-                var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
-
-                if (this.camera.getScene().useRightHandedSystem) {
-                    this.camera.cameraRotation.y -= offsetX / this.angularSensibility;
-                } else {
-                    this.camera.cameraRotation.y += offsetX / this.angularSensibility;
-                }
+                if (this.camera.getScene().useRightHandedSystem) offsetX *= -1;
+                if (this.camera.parent && this.camera.parent._getWorldMatrixDeterminant() < 0) offsetX *= -1;
+                this.camera.cameraRotation.y += offsetX / this.angularSensibility;
 
 
+                var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
                 this.camera.cameraRotation.x += offsetY / this.angularSensibility;
                 this.camera.cameraRotation.x += offsetY / this.angularSensibility;
 
 
                 this.previousPosition = null;
                 this.previousPosition = null;

+ 9 - 13
src/Cameras/babylon.arcRotateCamera.ts

@@ -340,8 +340,8 @@
 
 
         private _computationVector: Vector3 = Vector3.Zero();
         private _computationVector: Vector3 = Vector3.Zero();
 
 
-        constructor(name: string, alpha: number, beta: number, radius: number, target: Vector3, scene: Scene) {
-            super(name, Vector3.Zero(), scene);
+        constructor(name: string, alpha: number, beta: number, radius: number, target: Vector3, scene: Scene, setActiveOnSceneIfNoneActive = true) {
+            super(name, Vector3.Zero(), scene, setActiveOnSceneIfNoneActive);
 
 
             this._target = Vector3.Zero();
             this._target = Vector3.Zero();
             if (target) {
             if (target) {
@@ -484,12 +484,11 @@
             this.inputs.checkInputs();
             this.inputs.checkInputs();
             // Inertia
             // Inertia
             if (this.inertialAlphaOffset !== 0 || this.inertialBetaOffset !== 0 || this.inertialRadiusOffset !== 0) {
             if (this.inertialAlphaOffset !== 0 || this.inertialBetaOffset !== 0 || this.inertialRadiusOffset !== 0) {
-
-                if (this.getScene().useRightHandedSystem) {
-                    this.alpha -= this.beta <= 0 ? -this.inertialAlphaOffset : this.inertialAlphaOffset;
-                } else {
-                    this.alpha += this.beta <= 0 ? -this.inertialAlphaOffset : this.inertialAlphaOffset;
-                }
+                let inertialAlphaOffset = this.inertialAlphaOffset;
+                if (this.beta <= 0) inertialAlphaOffset *= -1;
+                if (this.getScene().useRightHandedSystem) inertialAlphaOffset *= -1;
+                if (this.parent && this.parent._getWorldMatrixDeterminant() < 0) inertialAlphaOffset *= -1;
+                this.alpha += inertialAlphaOffset;
 
 
                 this.beta += this.inertialBetaOffset;
                 this.beta += this.inertialBetaOffset;
 
 
@@ -673,11 +672,8 @@
                     up = up.negate();
                     up = up.negate();
                 }
                 }
 
 
-                if (this.getScene().useRightHandedSystem) {
-                    Matrix.LookAtRHToRef(this.position, target, up, this._viewMatrix);
-                } else {
-                    Matrix.LookAtLHToRef(this.position, target, up, this._viewMatrix);
-                }
+                this._computeViewMatrix(this.position, target, up);
+
                 this._viewMatrix.m[12] += this.targetScreenOffset.x;
                 this._viewMatrix.m[12] += this.targetScreenOffset.x;
                 this._viewMatrix.m[13] += this.targetScreenOffset.y;
                 this._viewMatrix.m[13] += this.targetScreenOffset.y;
             }
             }

+ 10 - 26
src/Cameras/babylon.camera.ts

@@ -160,22 +160,22 @@
         private _computedViewMatrix = Matrix.Identity();
         private _computedViewMatrix = Matrix.Identity();
         public _projectionMatrix = new Matrix();
         public _projectionMatrix = new Matrix();
         private _doNotComputeProjectionMatrix = false;
         private _doNotComputeProjectionMatrix = false;
-        private _worldMatrix: Matrix;
+        private _worldMatrix = Matrix.Identity();
         public _postProcesses = new Array<Nullable<PostProcess>>();
         public _postProcesses = new Array<Nullable<PostProcess>>();
         private _transformMatrix = Matrix.Zero();
         private _transformMatrix = Matrix.Zero();
 
 
         public _activeMeshes = new SmartArray<AbstractMesh>(256);
         public _activeMeshes = new SmartArray<AbstractMesh>(256);
 
 
-        private _globalPosition = Vector3.Zero();
+        protected _globalPosition = Vector3.Zero();
         private _frustumPlanes: Plane[];
         private _frustumPlanes: Plane[];
         private _refreshFrustumPlanes = true;
         private _refreshFrustumPlanes = true;
 
 
-        constructor(name: string, position: Vector3, scene: Scene) {
+        constructor(name: string, position: Vector3, scene: Scene, setActiveOnSceneIfNoneActive = true) {
             super(name, scene);
             super(name, scene);
 
 
             this.getScene().addCamera(this);
             this.getScene().addCamera(this);
 
 
-            if (!this.getScene().activeCamera) {
+            if (setActiveOnSceneIfNoneActive && !this.getScene().activeCamera) {
                 this.getScene().activeCamera = this;
                 this.getScene().activeCamera = this;
             }
             }
 
 
@@ -435,13 +435,12 @@
         }
         }
 
 
         public getWorldMatrix(): Matrix {
         public getWorldMatrix(): Matrix {
-            if (!this._worldMatrix) {
-                this._worldMatrix = Matrix.Identity();
+            if (this._isSynchronizedViewMatrix()) {
+                return this._worldMatrix;
             }
             }
 
 
-            var viewMatrix = this.getViewMatrix();
-
-            viewMatrix.invertToRef(this._worldMatrix);
+            // Getting the the view matrix will also compute the world matrix.
+            this.getViewMatrix();
 
 
             return this._worldMatrix;
             return this._worldMatrix;
         }
         }
@@ -462,29 +461,14 @@
 
 
             this._refreshFrustumPlanes = true;
             this._refreshFrustumPlanes = true;
 
 
-            if (!this.parent || !this.parent.getWorldMatrix) {
-                this._globalPosition.copyFrom(this.position);
-            } else {
-                if (!this._worldMatrix) {
-                    this._worldMatrix = Matrix.Identity();
-                }
-
-                this._computedViewMatrix.invertToRef(this._worldMatrix);
-
-                this._worldMatrix.multiplyToRef(this.parent.getWorldMatrix(), this._computedViewMatrix);
-                this._globalPosition.copyFromFloats(this._computedViewMatrix.m[12], this._computedViewMatrix.m[13], this._computedViewMatrix.m[14]);
-
-                this._computedViewMatrix.invert();
-
-                this._markSyncedWithParent();
-            }
-
             if (this._cameraRigParams && this._cameraRigParams.vrPreViewMatrix) {
             if (this._cameraRigParams && this._cameraRigParams.vrPreViewMatrix) {
                 this._computedViewMatrix.multiplyToRef(this._cameraRigParams.vrPreViewMatrix, this._computedViewMatrix);
                 this._computedViewMatrix.multiplyToRef(this._cameraRigParams.vrPreViewMatrix, this._computedViewMatrix);
             }
             }
 
 
             this.onViewMatrixChangedObservable.notifyObservers(this);
             this.onViewMatrixChangedObservable.notifyObservers(this);
 
 
+            this._computedViewMatrix.invertToRef(this._worldMatrix);
+
             return this._computedViewMatrix;
             return this._computedViewMatrix;
         }
         }
 
 

+ 2 - 2
src/Cameras/babylon.freeCamera.ts

@@ -106,8 +106,8 @@
         public _localDirection: Vector3;
         public _localDirection: Vector3;
         public _transformedDirection: Vector3;
         public _transformedDirection: Vector3;
 
 
-        constructor(name: string, position: Vector3, scene: Scene) {
-            super(name, position, scene);
+        constructor(name: string, position: Vector3, scene: Scene, setActiveOnSceneIfNoneActive = true) {
+            super(name, position, scene, setActiveOnSceneIfNoneActive);
             this.inputs = new FreeCameraInputsManager(this);
             this.inputs = new FreeCameraInputsManager(this);
             this.inputs.addKeyboard().addMouse();
             this.inputs.addKeyboard().addMouse();
         }
         }

+ 123 - 0
src/Cameras/babylon.stereoscopicCameras.ts

@@ -1,53 +1,124 @@
 module BABYLON {
 module BABYLON {
+    /**
+     * Camera used to simulate anaglyphic rendering (based on FreeCamera)
+     */
     export class AnaglyphFreeCamera extends FreeCamera {
     export class AnaglyphFreeCamera extends FreeCamera {
+        /**
+         * Creates a new AnaglyphFreeCamera
+         * @param name defines camera name
+         * @param position defines initial position
+         * @param interaxialDistance defines distance between each color axis
+         * @param scene defines the hosting scene
+         */
         constructor(name: string, position: Vector3, interaxialDistance: number, scene: Scene) {
         constructor(name: string, position: Vector3, interaxialDistance: number, scene: Scene) {
             super(name, position, scene);
             super(name, position, scene);
             this.interaxialDistance = interaxialDistance;
             this.interaxialDistance = interaxialDistance;
             this.setCameraRigMode(Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
             this.setCameraRigMode(Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
         }
         }
 
 
+        /**
+         * Gets camera class name
+         * @returns AnaglyphFreeCamera
+         */
         public getClassName(): string {
         public getClassName(): string {
             return "AnaglyphFreeCamera";
             return "AnaglyphFreeCamera";
         }
         }
     }
     }
 
 
+    /**
+     * Camera used to simulate anaglyphic rendering (based on ArcRotateCamera)
+     */    
     export class AnaglyphArcRotateCamera extends ArcRotateCamera {
     export class AnaglyphArcRotateCamera extends ArcRotateCamera {
+
+        /**
+         * Creates a new AnaglyphArcRotateCamera
+         * @param name defines camera name
+         * @param alpha defines alpha angle (in radians)
+         * @param beta defines beta angle (in radians)
+         * @param radius defines radius
+         * @param target defines camera target 
+         * @param interaxialDistance defines distance between each color axis
+         * @param scene defines the hosting scene
+         */
         constructor(name: string, alpha: number, beta: number, radius: number, target: Vector3, interaxialDistance: number, scene: Scene) {
         constructor(name: string, alpha: number, beta: number, radius: number, target: Vector3, interaxialDistance: number, scene: Scene) {
             super(name, alpha, beta, radius, target, scene);
             super(name, alpha, beta, radius, target, scene);
             this.interaxialDistance = interaxialDistance;
             this.interaxialDistance = interaxialDistance;
             this.setCameraRigMode(Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
             this.setCameraRigMode(Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
         }
         }
 
 
+        /**
+         * Gets camera class name
+         * @returns AnaglyphArcRotateCamera
+         */        
         public getClassName(): string {
         public getClassName(): string {
             return "AnaglyphArcRotateCamera";
             return "AnaglyphArcRotateCamera";
         }
         }
     }
     }
 
 
+    /**
+     * Camera used to simulate anaglyphic rendering (based on GamepadCamera)
+     */       
     export class AnaglyphGamepadCamera extends GamepadCamera {
     export class AnaglyphGamepadCamera extends GamepadCamera {
+        /**
+         * Creates a new AnaglyphGamepadCamera
+         * @param name defines camera name
+         * @param position defines initial position
+         * @param interaxialDistance defines distance between each color axis
+         * @param scene defines the hosting scene
+         */
         constructor(name: string, position: Vector3, interaxialDistance: number, scene: Scene) {
         constructor(name: string, position: Vector3, interaxialDistance: number, scene: Scene) {
             super(name, position, scene);
             super(name, position, scene);
             this.interaxialDistance = interaxialDistance;
             this.interaxialDistance = interaxialDistance;
             this.setCameraRigMode(Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
             this.setCameraRigMode(Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
         }
         }
 
 
+        /**
+         * Gets camera class name
+         * @returns AnaglyphGamepadCamera
+         */   
         public getClassName(): string {
         public getClassName(): string {
             return "AnaglyphGamepadCamera";
             return "AnaglyphGamepadCamera";
         }
         }
     }
     }
 
 
+    /**
+     * Camera used to simulate anaglyphic rendering (based on UniversalCamera)
+     */        
     export class AnaglyphUniversalCamera extends UniversalCamera {
     export class AnaglyphUniversalCamera extends UniversalCamera {
+        /**
+         * Creates a new AnaglyphUniversalCamera
+         * @param name defines camera name
+         * @param position defines initial position
+         * @param interaxialDistance defines distance between each color axis
+         * @param scene defines the hosting scene
+         */
         constructor(name: string, position: Vector3, interaxialDistance: number, scene: Scene) {
         constructor(name: string, position: Vector3, interaxialDistance: number, scene: Scene) {
             super(name, position, scene);
             super(name, position, scene);
             this.interaxialDistance = interaxialDistance;
             this.interaxialDistance = interaxialDistance;
             this.setCameraRigMode(Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
             this.setCameraRigMode(Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
         }
         }
 
 
+        /**
+         * Gets camera class name
+         * @returns AnaglyphUniversalCamera
+         */           
         public getClassName(): string {
         public getClassName(): string {
             return "AnaglyphUniversalCamera";
             return "AnaglyphUniversalCamera";
         }
         }
     }
     }
 
 
+    /**
+     * Camera used to simulate stereoscopic rendering (based on FreeCamera)
+     */    
     export class StereoscopicFreeCamera extends FreeCamera {
     export class StereoscopicFreeCamera extends FreeCamera {
+        /**
+         * Creates a new StereoscopicFreeCamera
+         * @param name defines camera name
+         * @param position defines initial position
+         * @param interaxialDistance defines distance between each color axis
+         * @param isStereoscopicSideBySide defines is stereoscopic is done side by side or over under
+         * @param scene defines the hosting scene
+         */
         constructor(name: string, position: Vector3, interaxialDistance: number, isStereoscopicSideBySide: boolean, scene: Scene) {
         constructor(name: string, position: Vector3, interaxialDistance: number, isStereoscopicSideBySide: boolean, scene: Scene) {
             super(name, position, scene);
             super(name, position, scene);
             this.interaxialDistance = interaxialDistance;
             this.interaxialDistance = interaxialDistance;
@@ -55,12 +126,30 @@
             this.setCameraRigMode(isStereoscopicSideBySide ? Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
             this.setCameraRigMode(isStereoscopicSideBySide ? Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
         }
         }
 
 
+        /**
+         * Gets camera class name
+         * @returns StereoscopicFreeCamera
+         */            
         public getClassName(): string {
         public getClassName(): string {
             return "StereoscopicFreeCamera";
             return "StereoscopicFreeCamera";
         }
         }
     }
     }
 
 
+    /**
+     * Camera used to simulate stereoscopic rendering (based on ArcRotateCamera)
+     */      
     export class StereoscopicArcRotateCamera extends ArcRotateCamera {
     export class StereoscopicArcRotateCamera extends ArcRotateCamera {
+        /**
+         * Creates a new StereoscopicArcRotateCamera
+         * @param name defines camera name
+         * @param alpha defines alpha angle (in radians)
+         * @param beta defines beta angle (in radians)
+         * @param radius defines radius
+         * @param target defines camera target 
+         * @param interaxialDistance defines distance between each color axis
+         * @param isStereoscopicSideBySide defines is stereoscopic is done side by side or over under
+         * @param scene defines the hosting scene
+         */        
         constructor(name: string, alpha: number, beta: number, radius: number, target: Vector3, interaxialDistance: number, isStereoscopicSideBySide: boolean, scene: Scene) {
         constructor(name: string, alpha: number, beta: number, radius: number, target: Vector3, interaxialDistance: number, isStereoscopicSideBySide: boolean, scene: Scene) {
             super(name, alpha, beta, radius, target, scene);
             super(name, alpha, beta, radius, target, scene);
             this.interaxialDistance = interaxialDistance;
             this.interaxialDistance = interaxialDistance;
@@ -68,12 +157,27 @@
             this.setCameraRigMode(isStereoscopicSideBySide ? Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
             this.setCameraRigMode(isStereoscopicSideBySide ? Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
         }
         }
 
 
+        /**
+         * Gets camera class name
+         * @returns StereoscopicArcRotateCamera
+         */              
         public getClassName(): string {
         public getClassName(): string {
             return "StereoscopicArcRotateCamera";
             return "StereoscopicArcRotateCamera";
         }
         }
     }
     }
 
 
+    /**
+     * Camera used to simulate stereoscopic rendering (based on GamepadCamera)
+     */      
     export class StereoscopicGamepadCamera extends GamepadCamera {
     export class StereoscopicGamepadCamera extends GamepadCamera {
+        /**
+         * Creates a new StereoscopicGamepadCamera
+         * @param name defines camera name
+         * @param position defines initial position
+         * @param interaxialDistance defines distance between each color axis
+         * @param isStereoscopicSideBySide defines is stereoscopic is done side by side or over under
+         * @param scene defines the hosting scene
+         */        
         constructor(name: string, position: Vector3, interaxialDistance: number, isStereoscopicSideBySide: boolean, scene: Scene) {
         constructor(name: string, position: Vector3, interaxialDistance: number, isStereoscopicSideBySide: boolean, scene: Scene) {
             super(name, position, scene);
             super(name, position, scene);
             this.interaxialDistance = interaxialDistance;
             this.interaxialDistance = interaxialDistance;
@@ -81,12 +185,27 @@
             this.setCameraRigMode(isStereoscopicSideBySide ? Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
             this.setCameraRigMode(isStereoscopicSideBySide ? Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
         }
         }
 
 
+        /**
+         * Gets camera class name
+         * @returns StereoscopicGamepadCamera
+         */              
         public getClassName(): string {
         public getClassName(): string {
             return "StereoscopicGamepadCamera";
             return "StereoscopicGamepadCamera";
         }
         }
     }
     }
 
 
+    /**
+     * Camera used to simulate stereoscopic rendering (based on UniversalCamera)
+     */      
     export class StereoscopicUniversalCamera extends UniversalCamera {
     export class StereoscopicUniversalCamera extends UniversalCamera {
+        /**
+         * Creates a new StereoscopicUniversalCamera
+         * @param name defines camera name
+         * @param position defines initial position
+         * @param interaxialDistance defines distance between each color axis
+         * @param isStereoscopicSideBySide defines is stereoscopic is done side by side or over under
+         * @param scene defines the hosting scene
+         */        
         constructor(name: string, position: Vector3, interaxialDistance: number, isStereoscopicSideBySide: boolean, scene: Scene) {
         constructor(name: string, position: Vector3, interaxialDistance: number, isStereoscopicSideBySide: boolean, scene: Scene) {
             super(name, position, scene);
             super(name, position, scene);
             this.interaxialDistance = interaxialDistance;
             this.interaxialDistance = interaxialDistance;
@@ -94,6 +213,10 @@
             this.setCameraRigMode(isStereoscopicSideBySide ? Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
             this.setCameraRigMode(isStereoscopicSideBySide ? Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
         }
         }
 
 
+        /**
+         * Gets camera class name
+         * @returns StereoscopicUniversalCamera
+         */              
         public getClassName(): string {
         public getClassName(): string {
             return "StereoscopicUniversalCamera";
             return "StereoscopicUniversalCamera";
         }
         }

+ 24 - 8
src/Cameras/babylon.targetCamera.ts

@@ -27,13 +27,14 @@
         public _referencePoint = new Vector3(0, 0, 1);
         public _referencePoint = new Vector3(0, 0, 1);
         private _currentUpVector = new Vector3(0, 1, 0);
         private _currentUpVector = new Vector3(0, 1, 0);
         public _transformedReferencePoint = Vector3.Zero();
         public _transformedReferencePoint = Vector3.Zero();
-        public _lookAtTemp = Matrix.Zero();
-        public _tempMatrix = Matrix.Zero();
+
+        protected _globalCurrentTarget = Vector3.Zero();
+        protected _globalCurrentUpVector = Vector3.Zero();
 
 
         public _reset: () => void;
         public _reset: () => void;
 
 
-        constructor(name: string, position: Vector3, scene: Scene) {
-            super(name, position, scene);
+        constructor(name: string, position: Vector3, scene: Scene, setActiveOnSceneIfNoneActive = true) {
+            super(name, position, scene, setActiveOnSceneIfNoneActive);
         }
         }
 
 
         public getFrontPosition(distance: number): Vector3 {
         public getFrontPosition(distance: number): Vector3 {
@@ -290,13 +291,28 @@
             // Computing target and final matrix
             // Computing target and final matrix
             this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
             this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
 
 
-            if (this.getScene().useRightHandedSystem) {
-                Matrix.LookAtRHToRef(this.position, this._currentTarget, this._currentUpVector, this._viewMatrix);
+            this._computeViewMatrix(this.position, this._currentTarget, this._currentUpVector);
+            return this._viewMatrix;
+        }
+
+        protected _computeViewMatrix(position: Vector3, target: Vector3, up: Vector3): void {
+            if (this.parent) {
+                const parentWorldMatrix = this.parent.getWorldMatrix();
+                Vector3.TransformCoordinatesToRef(this.position, parentWorldMatrix, this._globalPosition);
+                Vector3.TransformCoordinatesToRef(target, parentWorldMatrix, this._globalCurrentTarget);
+                Vector3.TransformNormalToRef(up, parentWorldMatrix, this._globalCurrentUpVector);
+                this._markSyncedWithParent();
             } else {
             } else {
-                Matrix.LookAtLHToRef(this.position, this._currentTarget, this._currentUpVector, this._viewMatrix);
+                this._globalPosition.copyFrom(this.position);
+                this._globalCurrentTarget.copyFrom(target);
+                this._globalCurrentUpVector.copyFrom(up);
             }
             }
 
 
-            return this._viewMatrix;
+            if (this.getScene().useRightHandedSystem) {
+                Matrix.LookAtRHToRef(this._globalPosition, this._globalCurrentTarget, this._globalCurrentUpVector, this._viewMatrix);
+            } else {
+                Matrix.LookAtLHToRef(this._globalPosition, this._globalCurrentTarget, this._globalCurrentUpVector, this._viewMatrix);
+            }
         }
         }
 
 
         /**
         /**

+ 54 - 46
src/Engine/babylon.engine.ts

@@ -843,7 +843,7 @@
          */
          */
         public disableUniformBuffers = false;
         public disableUniformBuffers = false;
 
 
-        /** @ignore */
+        /** @hidden */
         public _uniformBuffers = new Array<UniformBuffer>();
         public _uniformBuffers = new Array<UniformBuffer>();
 
 
         /**
         /**
@@ -890,10 +890,10 @@
             return this._webGLVersion < 2 || this.forcePOTTextures;
             return this._webGLVersion < 2 || this.forcePOTTextures;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _badOS = false;
         public _badOS = false;
 
 
-        /** @ignore */
+        /** @hidden */
         public _badDesktopOS = false;
         public _badDesktopOS = false;
 
 
         /**
         /**
@@ -906,7 +906,7 @@
         /** 
         /** 
          * Gets the audio engine 
          * Gets the audio engine 
          * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music
          * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music
-         * @ignoreNaming
+         * @ignorenaming
          */
          */
         public static audioEngine: AudioEngine;
         public static audioEngine: AudioEngine;
 
 
@@ -942,7 +942,7 @@
         public onVRRequestPresentStart = new Observable<Engine>();
         public onVRRequestPresentStart = new Observable<Engine>();
 
 
         private _hardwareScalingLevel: number;
         private _hardwareScalingLevel: number;
-        /** @ignore */
+        /** @hidden */
         protected _caps: EngineCapabilities;
         protected _caps: EngineCapabilities;
         private _pointerLockRequested: boolean;
         private _pointerLockRequested: boolean;
         private _isStencilEnable: boolean;
         private _isStencilEnable: boolean;
@@ -950,9 +950,9 @@
 
 
         private _loadingScreen: ILoadingScreen;
         private _loadingScreen: ILoadingScreen;
 
 
-        /** @ignore */
+        /** @hidden */
         public _drawCalls = new PerfCounter();
         public _drawCalls = new PerfCounter();
-        /** @ignore */
+        /** @hidden */
         public _textureCollisions = new PerfCounter();
         public _textureCollisions = new PerfCounter();
 
 
         private _glVersion: string;
         private _glVersion: string;
@@ -1000,42 +1000,42 @@
         }
         }
 
 
         // States
         // States
-        /** @ignore */
+        /** @hidden */
         protected _depthCullingState = new _DepthCullingState();
         protected _depthCullingState = new _DepthCullingState();
-        /** @ignore */
+        /** @hidden */
         protected _stencilState = new _StencilState();
         protected _stencilState = new _StencilState();
-        /** @ignore */
+        /** @hidden */
         protected _alphaState = new _AlphaState();
         protected _alphaState = new _AlphaState();
-        /** @ignore */
+        /** @hidden */
         protected _alphaMode = Engine.ALPHA_DISABLE;
         protected _alphaMode = Engine.ALPHA_DISABLE;
 
 
         // Cache
         // Cache
         private _internalTexturesCache = new Array<InternalTexture>();
         private _internalTexturesCache = new Array<InternalTexture>();
-        /** @ignore */
+        /** @hidden */
         protected _activeChannel = 0;
         protected _activeChannel = 0;
         private _currentTextureChannel = -1;    
         private _currentTextureChannel = -1;    
-        /** @ignore */
+        /** @hidden */
         protected _boundTexturesCache: { [key: string]: Nullable<InternalTexture> } = {};
         protected _boundTexturesCache: { [key: string]: Nullable<InternalTexture> } = {};
-        /** @ignore */
+        /** @hidden */
         protected _currentEffect: Nullable<Effect>;
         protected _currentEffect: Nullable<Effect>;
-        /** @ignore */
+        /** @hidden */
         protected _currentProgram: Nullable<WebGLProgram>;
         protected _currentProgram: Nullable<WebGLProgram>;
         private _compiledEffects: { [key: string]: Effect } = {}
         private _compiledEffects: { [key: string]: Effect } = {}
         private _vertexAttribArraysEnabled: boolean[] = [];
         private _vertexAttribArraysEnabled: boolean[] = [];
-        /** @ignore */
+        /** @hidden */
         protected _cachedViewport: Nullable<Viewport>;
         protected _cachedViewport: Nullable<Viewport>;
         private _cachedVertexArrayObject: Nullable<WebGLVertexArrayObject>;
         private _cachedVertexArrayObject: Nullable<WebGLVertexArrayObject>;
-        /** @ignore */
+        /** @hidden */
         protected _cachedVertexBuffers: any;
         protected _cachedVertexBuffers: any;
-        /** @ignore */
+        /** @hidden */
         protected _cachedIndexBuffer: Nullable<WebGLBuffer>;
         protected _cachedIndexBuffer: Nullable<WebGLBuffer>;
-        /** @ignore */
+        /** @hidden */
         protected _cachedEffectForVertexBuffers: Nullable<Effect>;
         protected _cachedEffectForVertexBuffers: Nullable<Effect>;
-        /** @ignore */
+        /** @hidden */
         protected _currentRenderTarget: Nullable<InternalTexture>;
         protected _currentRenderTarget: Nullable<InternalTexture>;
         private _uintIndicesCurrentlySet = false;
         private _uintIndicesCurrentlySet = false;
         private _currentBoundBuffer = new Array<Nullable<WebGLBuffer>>();
         private _currentBoundBuffer = new Array<Nullable<WebGLBuffer>>();
-        /** @ignore */
+        /** @hidden */
         protected _currentFramebuffer: Nullable<WebGLFramebuffer>;
         protected _currentFramebuffer: Nullable<WebGLFramebuffer>;
         private _currentBufferPointers = new Array<BufferPointer>();
         private _currentBufferPointers = new Array<BufferPointer>();
         private _currentInstanceLocations = new Array<number>();
         private _currentInstanceLocations = new Array<number>();
@@ -1805,13 +1805,13 @@
             return this._caps;
             return this._caps;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public get drawCalls(): number {
         public get drawCalls(): number {
             Tools.Warn("drawCalls is deprecated. Please use SceneInstrumentation class");
             Tools.Warn("drawCalls is deprecated. Please use SceneInstrumentation class");
             return 0;
             return 0;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public get drawCallsPerfCounter(): Nullable<PerfCounter> {
         public get drawCallsPerfCounter(): Nullable<PerfCounter> {
             Tools.Warn("drawCallsPerfCounter is deprecated. Please use SceneInstrumentation class");
             Tools.Warn("drawCallsPerfCounter is deprecated. Please use SceneInstrumentation class");
             return null;
             return null;
@@ -2030,7 +2030,7 @@
             }
             }
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _renderLoop(): void {
         public _renderLoop(): void {
             if (!this._contextWasLost) {
             if (!this._contextWasLost) {
                 var shouldRender = true;
                 var shouldRender = true;
@@ -3123,7 +3123,7 @@
             this._gl.deleteVertexArray(vao);
             this._gl.deleteVertexArray(vao);
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _releaseBuffer(buffer: WebGLBuffer): boolean {
         public _releaseBuffer(buffer: WebGLBuffer): boolean {
             buffer.references--;
             buffer.references--;
 
 
@@ -3324,7 +3324,7 @@
 
 
         // Shaders
         // Shaders
         
         
-        /** @ignore */
+        /** @hidden */
         public _releaseEffect(effect: Effect): void {
         public _releaseEffect(effect: Effect): void {
             if (this._compiledEffects[effect._key]) {
             if (this._compiledEffects[effect._key]) {
                 delete this._compiledEffects[effect._key];
                 delete this._compiledEffects[effect._key];
@@ -3333,7 +3333,7 @@
             }
             }
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _deleteProgram(program: WebGLProgram): void {
         public _deleteProgram(program: WebGLProgram): void {
             if (program) {
             if (program) {
                 program.__SPECTOR_rebuildProgram = null;
                 program.__SPECTOR_rebuildProgram = null;
@@ -4084,7 +4084,7 @@
             return null;
             return null;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _createTexture(): WebGLTexture {
         public _createTexture(): WebGLTexture {
             let texture = this._gl.createTexture();
             let texture = this._gl.createTexture();
 
 
@@ -5235,12 +5235,12 @@
             return samples;
             return samples;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _uploadDataToTexture(target: number, lod: number, internalFormat: number, width: number, height: number, format: number, type: number, data: ArrayBufferView) {
         public _uploadDataToTexture(target: number, lod: number, internalFormat: number, width: number, height: number, format: number, type: number, data: ArrayBufferView) {
             this._gl.texImage2D(target, lod, internalFormat, width, height, 0, format, type, data);
             this._gl.texImage2D(target, lod, internalFormat, width, height, 0, format, type, data);
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _uploadCompressedDataToTexture(target: number, lod: number, internalFormat: number, width: number, height: number, data: ArrayBufferView) {
         public _uploadCompressedDataToTexture(target: number, lod: number, internalFormat: number, width: number, height: number, data: ArrayBufferView) {
             this._gl.compressedTexImage2D(target, lod, internalFormat, width, height, 0, <DataView>data);
             this._gl.compressedTexImage2D(target, lod, internalFormat, width, height, 0, <DataView>data);
         }
         }
@@ -5349,6 +5349,9 @@
                 }
                 }
 
 
                 let texture = loadData.texture as InternalTexture;
                 let texture = loadData.texture as InternalTexture;
+                if(loadData.info.sphericalPolynomial){
+                    texture._sphericalPolynomial = loadData.info.sphericalPolynomial;
+                }
                 texture._dataSource = InternalTexture.DATASOURCE_CUBEPREFILTERED;
                 texture._dataSource = InternalTexture.DATASOURCE_CUBEPREFILTERED;
                 texture._lodGenerationScale = scale;
                 texture._lodGenerationScale = scale;
                 texture._lodGenerationOffset = offset;
                 texture._lodGenerationOffset = offset;
@@ -5421,7 +5424,7 @@
                 }
                 }
             };
             };
 
 
-            return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension);
+            return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension, true);
         }
         }
 
 
         /**
         /**
@@ -5434,9 +5437,10 @@
          * @param onError defines an optional callback raised if there is an issue to load the texture
          * @param onError defines an optional callback raised if there is an issue to load the texture
          * @param format defines the format of the data
          * @param format defines the format of the data
          * @param forcedExtension defines the extension to use to pick the right loader
          * @param forcedExtension defines the extension to use to pick the right loader
+         * @param createPolynomials if a polynomial sphere should be created for the cube texture
          * @returns the cube texture as an InternalTexture
          * @returns the cube texture as an InternalTexture
          */
          */
-        public createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad: Nullable<(data?: any) => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, format?: number, forcedExtension: any = null): InternalTexture {
+        public createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad: Nullable<(data?: any) => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, format?: number, forcedExtension: any = null, createPolynomials = false): InternalTexture {
             var gl = this._gl;
             var gl = this._gl;
 
 
             var texture = new InternalTexture(this, InternalTexture.DATASOURCE_CUBE);
             var texture = new InternalTexture(this, InternalTexture.DATASOURCE_CUBE);
@@ -5527,7 +5531,10 @@
                     this._loadFile(rootUrl,
                     this._loadFile(rootUrl,
                         data => {
                         data => {
                             var info = DDSTools.GetDDSInfo(data);
                             var info = DDSTools.GetDDSInfo(data);
-
+                            if(createPolynomials){
+                                info.sphericalPolynomial = new SphericalPolynomial();
+                            }
+                            
                             var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
                             var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
 
 
                             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
                             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
@@ -5545,7 +5552,7 @@
                             texture.height = info.height;
                             texture.height = info.height;
                             texture.isReady = true;
                             texture.isReady = true;
                             texture.type = info.textureType;
                             texture.type = info.textureType;
-
+                            
                             if (onLoad) {
                             if (onLoad) {
                                 onLoad({ isDDS: true, width: info.width, info, data, texture });
                                 onLoad({ isDDS: true, width: info.width, info, data, texture });
                             }
                             }
@@ -5565,6 +5572,7 @@
                     var height = width;
                     var height = width;
 
 
                     this._prepareWorkingCanvas();
                     this._prepareWorkingCanvas();
+
                     if (!this._workingCanvas || !this._workingContext) {
                     if (!this._workingCanvas || !this._workingContext) {
                         return;
                         return;
                     }
                     }
@@ -6035,7 +6043,7 @@
             return rgbaData;
             return rgbaData;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _releaseFramebufferObjects(texture: InternalTexture): void {
         public _releaseFramebufferObjects(texture: InternalTexture): void {
             var gl = this._gl;
             var gl = this._gl;
 
 
@@ -6060,7 +6068,7 @@
             }
             }
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _releaseTexture(texture: InternalTexture): void {
         public _releaseTexture(texture: InternalTexture): void {
             var gl = this._gl;
             var gl = this._gl;
 
 
@@ -6213,7 +6221,7 @@
             }
             }
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         protected _bindTextureDirectly(target: number, texture: Nullable<InternalTexture>, forTextureDataUpdate = false, force = false): void {
         protected _bindTextureDirectly(target: number, texture: Nullable<InternalTexture>, forTextureDataUpdate = false, force = false): void {
             if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
             if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
                 this._activeChannel = texture._designatedSlot;
                 this._activeChannel = texture._designatedSlot;
@@ -6254,7 +6262,7 @@
             }
             }
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _bindTexture(channel: number, texture: Nullable<InternalTexture>): void {
         public _bindTexture(channel: number, texture: Nullable<InternalTexture>): void {
             if (channel < 0) {
             if (channel < 0) {
                 return;
                 return;
@@ -6499,7 +6507,7 @@
             }
             }
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _setAnisotropicLevel(target: number, texture: BaseTexture) {
         public _setAnisotropicLevel(target: number, texture: BaseTexture) {
             var internalTexture = texture.getInternalTexture();
             var internalTexture = texture.getInternalTexture();
 
 
@@ -6905,7 +6913,7 @@
             this._deltaTime = this._performanceMonitor.instantaneousFrameTime || 0;
             this._deltaTime = this._performanceMonitor.instantaneousFrameTime || 0;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _readTexturePixels(texture: InternalTexture, width: number, height: number, faceIndex = -1): ArrayBufferView {
         public _readTexturePixels(texture: InternalTexture, width: number, height: number, faceIndex = -1): ArrayBufferView {
             let gl = this._gl;
             let gl = this._gl;
             if (!this._dummyFramebuffer) {
             if (!this._dummyFramebuffer) {
@@ -7010,7 +7018,7 @@
             return successful;
             return successful;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _getWebGLTextureType(type: number): number {
         public _getWebGLTextureType(type: number): number {
             if (type === Engine.TEXTURETYPE_FLOAT) {
             if (type === Engine.TEXTURETYPE_FLOAT) {
                 return this._gl.FLOAT;
                 return this._gl.FLOAT;
@@ -7054,7 +7062,7 @@
             return internalFormat;
             return internalFormat;
         }        
         }        
 
 
-        /** @ignore */
+        /** @hidden */
         public _getRGBABufferInternalSizedFormat(type: number, format?: number): number {
         public _getRGBABufferInternalSizedFormat(type: number, format?: number): number {
             if (this._webGLVersion === 1) {
             if (this._webGLVersion === 1) {
                 if (format) {
                 if (format) {
@@ -7092,7 +7100,7 @@
             return this._gl.RGBA;
             return this._gl.RGBA;
         };
         };
 
 
-        /** @ignore */
+        /** @hidden */
         public _getRGBAMultiSampleBufferFormat(type: number): number {
         public _getRGBAMultiSampleBufferFormat(type: number): number {
             if (type === Engine.TEXTURETYPE_FLOAT) {
             if (type === Engine.TEXTURETYPE_FLOAT) {
                 return this._gl.RGBA32F;
                 return this._gl.RGBA32F;
@@ -7378,7 +7386,7 @@
             this._gl.bindBufferBase(this._gl.TRANSFORM_FEEDBACK_BUFFER, 0, value);
             this._gl.bindBufferBase(this._gl.TRANSFORM_FEEDBACK_BUFFER, 0, value);
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _loadFile(url: string, onSuccess: (data: string | ArrayBuffer, responseURL?: string) => void, onProgress?: (data: any) => void, database?: Database, useArrayBuffer?: boolean, onError?: (request?: XMLHttpRequest, exception?: any) => void): IFileRequest {
         public _loadFile(url: string, onSuccess: (data: string | ArrayBuffer, responseURL?: string) => void, onProgress?: (data: any) => void, database?: Database, useArrayBuffer?: boolean, onError?: (request?: XMLHttpRequest, exception?: any) => void): IFileRequest {
             let request = Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
             let request = Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
             this._activeRequests.push(request);
             this._activeRequests.push(request);
@@ -7388,7 +7396,7 @@
             return request;
             return request;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _loadFileAsync(url: string, database?: Database, useArrayBuffer?: boolean): Promise<string | ArrayBuffer> {
         public _loadFileAsync(url: string, database?: Database, useArrayBuffer?: boolean): Promise<string | ArrayBuffer> {
             return new Promise((resolve, reject) => {
             return new Promise((resolve, reject) => {
                 this._loadFile(url, (data) => {
                 this._loadFile(url, (data) => {
@@ -7432,7 +7440,7 @@
         /**
         /**
          * Gets a boolean indicating if the engine can be instanciated (ie. if a webGL context can be found)
          * Gets a boolean indicating if the engine can be instanciated (ie. if a webGL context can be found)
          * @returns true if the engine can be created
          * @returns true if the engine can be created
-         * @ignoreNaming
+         * @ignorenaming
          */
          */
         public static isSupported(): boolean {
         public static isSupported(): boolean {
             try {
             try {

+ 1 - 1
src/Gamepad/Controllers/babylon.poseEnabledController.ts

@@ -49,7 +49,7 @@ module BABYLON {
 
 
     /**
     /**
      * Defines the ExtendedGamepadButton interface for a gamepad button which includes state provided by a pose controller
      * Defines the ExtendedGamepadButton interface for a gamepad button which includes state provided by a pose controller
-     * @ignore
+     * @hidden
      */
      */
     export interface ExtendedGamepadButton extends GamepadButton {
     export interface ExtendedGamepadButton extends GamepadButton {
         /**
         /**

+ 1 - 1
src/Gamepad/Controllers/babylon.windowsMotionController.ts

@@ -264,7 +264,7 @@ module BABYLON {
          * Moves the axis on the controller mesh based on its current state
          * Moves the axis on the controller mesh based on its current state
          * @param axis the index of the axis
          * @param axis the index of the axis
          * @param axisValue the value of the axis which determines the meshes new position
          * @param axisValue the value of the axis which determines the meshes new position
-         * @ignore
+         * @hidden
          */
          */
         protected _lerpAxisTransform(axis: number, axisValue: number) {
         protected _lerpAxisTransform(axis: number, axisValue: number) {
             if (!this._loadedMeshInfo) {
             if (!this._loadedMeshInfo) {

+ 3 - 0
src/Instrumentation/babylon.timeToken.ts

@@ -1,4 +1,7 @@
 module BABYLON {
 module BABYLON {
+    /**
+     * @hidden
+     **/    
     export class _TimeToken {
     export class _TimeToken {
         public _startTimeQuery: Nullable<WebGLQuery>;
         public _startTimeQuery: Nullable<WebGLQuery>;
         public _endTimeQuery: Nullable<WebGLQuery>;
         public _endTimeQuery: Nullable<WebGLQuery>;

+ 1 - 1
src/Layer/babylon.effectLayer.ts

@@ -602,7 +602,7 @@
 
 
         /**
         /**
          * Rebuild the required buffers.
          * Rebuild the required buffers.
-         * @ignore Internal use only.
+         * @hidden Internal use only.
          */
          */
         public _rebuild(): void {
         public _rebuild(): void {
             let vb = this._vertexBuffers[VertexBuffer.PositionKind];
             let vb = this._vertexBuffers[VertexBuffer.PositionKind];

+ 1 - 1
src/Lights/babylon.hemisphericLight.ts

@@ -89,7 +89,7 @@
         }
         }
 
 
         /**
         /**
-         * @ignore internal use only.
+         * @hidden internal use only.
          */
          */
         public _getWorldMatrix(): Matrix {
         public _getWorldMatrix(): Matrix {
             if (!this._worldMatrix) {
             if (!this._worldMatrix) {

+ 6 - 6
src/Lights/babylon.light.ts

@@ -297,18 +297,18 @@ module BABYLON {
         public _shadowGenerator: Nullable<IShadowGenerator>;
         public _shadowGenerator: Nullable<IShadowGenerator>;
 
 
         /**
         /**
-         * @ignore Internal use only.
+         * @hidden Internal use only.
          */
          */
         public _excludedMeshesIds = new Array<string>();
         public _excludedMeshesIds = new Array<string>();
 
 
         /**
         /**
-         * @ignore Internal use only.
+         * @hidden Internal use only.
          */
          */
         public _includedOnlyMeshesIds = new Array<string>();
         public _includedOnlyMeshesIds = new Array<string>();
 
 
         /**
         /**
          * The current light unifom buffer.
          * The current light unifom buffer.
-         * @ignore Internal use only.
+         * @hidden Internal use only.
          */
          */
         public _uniformBuffer: UniformBuffer;
         public _uniformBuffer: UniformBuffer;
 
 
@@ -341,7 +341,7 @@ module BABYLON {
         public abstract transferToEffect(effect: Effect, lightIndex: string): Light;
         public abstract transferToEffect(effect: Effect, lightIndex: string): Light;
 
 
         /**
         /**
-         * @ignore internal use only.
+         * @hidden internal use only.
          */
          */
         public abstract _getWorldMatrix(): Matrix;
         public abstract _getWorldMatrix(): Matrix;
 
 
@@ -686,7 +686,7 @@ module BABYLON {
 
 
         /**
         /**
          * Forces the meshes to update their light related information in their rendering used effects
          * Forces the meshes to update their light related information in their rendering used effects
-         * @ignore Internal Use Only
+         * @hidden Internal Use Only
          */
          */
         public _markMeshesAsLightDirty() {
         public _markMeshesAsLightDirty() {
             for (var mesh of this.getScene().meshes) {
             for (var mesh of this.getScene().meshes) {
@@ -765,7 +765,7 @@ module BABYLON {
 
 
         /**
         /**
          * Reorder the light in the scene according to their defined priority.
          * Reorder the light in the scene according to their defined priority.
-         * @ignore Internal Use Only
+         * @hidden Internal Use Only
          */
          */
         public _reorderLightsInScene(): void {
         public _reorderLightsInScene(): void {
             var scene = this.getScene();
             var scene = this.getScene();

+ 1 - 1
src/Lights/babylon.shadowLight.ts

@@ -303,7 +303,7 @@
 
 
         /**
         /**
          * Get the world matrix of the sahdow lights.
          * Get the world matrix of the sahdow lights.
-         * @ignore Internal Use Only
+         * @hidden Internal Use Only
          */
          */
         public _getWorldMatrix(): Matrix {
         public _getWorldMatrix(): Matrix {
             if (!this._worldMatrix) {
             if (!this._worldMatrix) {

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

@@ -1,7 +1,7 @@
 module BABYLON {
 module BABYLON {
     /**
     /**
      * Background material defines definition.
      * Background material defines definition.
-     * @ignore Mainly internal Use
+     * @hidden Mainly internal Use
      */
      */
     class BackgroundMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines {
     class BackgroundMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines {
         /**
         /**

+ 1 - 1
src/Materials/PBR/babylon.pbrBaseMaterial.ts

@@ -1,7 +1,7 @@
 module BABYLON {
 module BABYLON {
     /**
     /**
      * Manages the defines for the PBR Material.
      * Manages the defines for the PBR Material.
-     * @ignoreChildren
+     * @hiddenChildren
      */
      */
     class PBRMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines {
     class PBRMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines {
         public PBR = true;
         public PBR = true;

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

@@ -164,7 +164,11 @@
 
 
         public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): CubeTexture {
         public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): CubeTexture {
             var texture = SerializationHelper.Parse(() => {
             var texture = SerializationHelper.Parse(() => {
-                return new CubeTexture(rootUrl + parsedTexture.name, scene, parsedTexture.extensions);
+                var prefiltered:boolean = false;
+                if (parsedTexture.prefiltered) {
+                    prefiltered = parsedTexture.prefiltered;
+                }
+                return new CubeTexture(rootUrl + parsedTexture.name, scene, parsedTexture.extensions, false, null, null, null, undefined, prefiltered);
             }, parsedTexture, scene);
             }, parsedTexture, scene);
 
 
             // Local Cubemaps
             // Local Cubemaps

+ 2 - 2
src/Materials/Textures/babylon.dynamicTexture.ts

@@ -35,7 +35,7 @@
             } else {
             } else {
                 this._canvas = document.createElement("canvas");
                 this._canvas = document.createElement("canvas");
 
 
-                if (options.width) {
+                if (options.width || options.width === 0) {
                     this._texture = this._engine.createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
                     this._texture = this._engine.createDynamicTexture(options.width, options.height, generateMipMaps, samplingMode);
                 } else {
                 } else {
                     this._texture = this._engine.createDynamicTexture(options, options, generateMipMaps, samplingMode);
                     this._texture = this._engine.createDynamicTexture(options, options, generateMipMaps, samplingMode);
@@ -177,7 +177,7 @@
             return newTexture;
             return newTexture;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _rebuild(): void {
         public _rebuild(): void {
             this.update();
             this.update();
         }
         }

+ 35 - 35
src/Materials/Textures/babylon.internalTexture.ts

@@ -133,78 +133,78 @@ module BABYLON {
         public next: Nullable<IInternalTextureTracker> = null
         public next: Nullable<IInternalTextureTracker> = null
 
 
         // Private
         // Private
-        /** @ignore */
+        /** @hidden */
         public _initialSlot = -1;
         public _initialSlot = -1;
-        /** @ignore */
+        /** @hidden */
         public _designatedSlot = -1;
         public _designatedSlot = -1;
-        /** @ignore */
+        /** @hidden */
         public _dataSource = InternalTexture.DATASOURCE_UNKNOWN;
         public _dataSource = InternalTexture.DATASOURCE_UNKNOWN;
-        /** @ignore */
+        /** @hidden */
         public _buffer: Nullable<ArrayBuffer | HTMLImageElement>;
         public _buffer: Nullable<ArrayBuffer | HTMLImageElement>;
-        /** @ignore */
+        /** @hidden */
         public _bufferView: Nullable<ArrayBufferView>;
         public _bufferView: Nullable<ArrayBufferView>;
-        /** @ignore */
+        /** @hidden */
         public _bufferViewArray: Nullable<ArrayBufferView[]>;
         public _bufferViewArray: Nullable<ArrayBufferView[]>;
-        /** @ignore */
+        /** @hidden */
         public _size: number;
         public _size: number;
-        /** @ignore */
+        /** @hidden */
         public _extension: string;
         public _extension: string;
-        /** @ignore */
+        /** @hidden */
         public _files: Nullable<string[]>;
         public _files: Nullable<string[]>;
-        /** @ignore */
+        /** @hidden */
         public _workingCanvas: HTMLCanvasElement;
         public _workingCanvas: HTMLCanvasElement;
-        /** @ignore */
+        /** @hidden */
         public _workingContext: CanvasRenderingContext2D;
         public _workingContext: CanvasRenderingContext2D;
-        /** @ignore */
+        /** @hidden */
         public _framebuffer: Nullable<WebGLFramebuffer>;
         public _framebuffer: Nullable<WebGLFramebuffer>;
-        /** @ignore */
+        /** @hidden */
         public _depthStencilBuffer: Nullable<WebGLRenderbuffer>;
         public _depthStencilBuffer: Nullable<WebGLRenderbuffer>;
-        /** @ignore */
+        /** @hidden */
         public _MSAAFramebuffer: Nullable<WebGLFramebuffer>;
         public _MSAAFramebuffer: Nullable<WebGLFramebuffer>;
-        /** @ignore */
+        /** @hidden */
         public _MSAARenderBuffer: Nullable<WebGLRenderbuffer>;
         public _MSAARenderBuffer: Nullable<WebGLRenderbuffer>;
-        /** @ignore */
+        /** @hidden */
         public _attachments: Nullable<number[]>;
         public _attachments: Nullable<number[]>;
-        /** @ignore */
+        /** @hidden */
         public _cachedCoordinatesMode: Nullable<number>;
         public _cachedCoordinatesMode: Nullable<number>;
-        /** @ignore */
+        /** @hidden */
         public _cachedWrapU: Nullable<number>;
         public _cachedWrapU: Nullable<number>;
-        /** @ignore */
+        /** @hidden */
         public _cachedWrapV: Nullable<number>;
         public _cachedWrapV: Nullable<number>;
-        /** @ignore */
+        /** @hidden */
         public _cachedWrapR: Nullable<number>;
         public _cachedWrapR: Nullable<number>;
-        /** @ignore */
+        /** @hidden */
         public _cachedAnisotropicFilteringLevel: Nullable<number>;
         public _cachedAnisotropicFilteringLevel: Nullable<number>;
-        /** @ignore */
+        /** @hidden */
         public _isDisabled: boolean;
         public _isDisabled: boolean;
-        /** @ignore */
+        /** @hidden */
         public _compression: Nullable<string>;
         public _compression: Nullable<string>;
-        /** @ignore */
+        /** @hidden */
         public _generateStencilBuffer: boolean;
         public _generateStencilBuffer: boolean;
-        /** @ignore */
+        /** @hidden */
         public _generateDepthBuffer: boolean;
         public _generateDepthBuffer: boolean;
-        /** @ignore */
+        /** @hidden */
         public _comparisonFunction: number = 0;
         public _comparisonFunction: number = 0;
-        /** @ignore */
+        /** @hidden */
         public _sphericalPolynomial: Nullable<SphericalPolynomial>;
         public _sphericalPolynomial: Nullable<SphericalPolynomial>;
-        /** @ignore */
+        /** @hidden */
         public _lodGenerationScale: number;
         public _lodGenerationScale: number;
-        /** @ignore */
+        /** @hidden */
         public _lodGenerationOffset: number;
         public _lodGenerationOffset: number;
 
 
         // The following three fields helps sharing generated fixed LODs for texture filtering
         // The following three fields helps sharing generated fixed LODs for texture filtering
         // In environment not supporting the textureLOD extension like EDGE. They are for internal use only.
         // In environment not supporting the textureLOD extension like EDGE. They are for internal use only.
         // They are at the level of the gl texture to benefit from the cache.
         // They are at the level of the gl texture to benefit from the cache.
-        /** @ignore */
+        /** @hidden */
         public _lodTextureHigh: BaseTexture;
         public _lodTextureHigh: BaseTexture;
-        /** @ignore */
+        /** @hidden */
         public _lodTextureMid: BaseTexture;
         public _lodTextureMid: BaseTexture;
-        /** @ignore */
+        /** @hidden */
         public _lodTextureLow: BaseTexture;
         public _lodTextureLow: BaseTexture;
 
 
-        /** @ignore */
+        /** @hidden */
         public _webGLTexture: Nullable<WebGLTexture>;
         public _webGLTexture: Nullable<WebGLTexture>;
-        /** @ignore */
+        /** @hidden */
         public _references: number = 1;
         public _references: number = 1;
         private _engine: Engine;
         private _engine: Engine;
 
 
@@ -252,7 +252,7 @@ module BABYLON {
             this._size = width * height * depth;
             this._size = width * height * depth;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _rebuild(): void {
         public _rebuild(): void {
             var proxy: InternalTexture;
             var proxy: InternalTexture;
             this.isReady = false;
             this.isReady = false;

+ 6 - 6
src/Materials/babylon.effect.ts

@@ -451,7 +451,7 @@
             });
             });
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _loadVertexShader(vertex: any, callback: (data: any) => void): void {
         public _loadVertexShader(vertex: any, callback: (data: any) => void): void {
             if (Tools.IsWindowObjectExist()) {
             if (Tools.IsWindowObjectExist()) {
                 // DOM element ?
                 // DOM element ?
@@ -487,7 +487,7 @@
             this._engine._loadFile(vertexShaderUrl + ".vertex.fx", callback);
             this._engine._loadFile(vertexShaderUrl + ".vertex.fx", callback);
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _loadFragmentShader(fragment: any, callback: (data: any) => void): void {
         public _loadFragmentShader(fragment: any, callback: (data: any) => void): void {
             if (Tools.IsWindowObjectExist()) {
             if (Tools.IsWindowObjectExist()) {
                 // DOM element ?
                 // DOM element ?
@@ -913,7 +913,7 @@
             this._engine.setTextureFromPostProcessOutput(this._samplers.indexOf(channel), postProcess);
             this._engine.setTextureFromPostProcessOutput(this._samplers.indexOf(channel), postProcess);
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _cacheMatrix(uniformName: string, matrix: Matrix): boolean {
         public _cacheMatrix(uniformName: string, matrix: Matrix): boolean {
             var cache = this._valueCache[uniformName];
             var cache = this._valueCache[uniformName];
             var flag = matrix.updateFlag;
             var flag = matrix.updateFlag;
@@ -926,7 +926,7 @@
             return true;
             return true;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _cacheFloat2(uniformName: string, x: number, y: number): boolean {
         public _cacheFloat2(uniformName: string, x: number, y: number): boolean {
             var cache = this._valueCache[uniformName];
             var cache = this._valueCache[uniformName];
             if (!cache) {
             if (!cache) {
@@ -948,7 +948,7 @@
             return changed;
             return changed;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _cacheFloat3(uniformName: string, x: number, y: number, z: number): boolean {
         public _cacheFloat3(uniformName: string, x: number, y: number, z: number): boolean {
             var cache = this._valueCache[uniformName];
             var cache = this._valueCache[uniformName];
             if (!cache) {
             if (!cache) {
@@ -974,7 +974,7 @@
             return changed;
             return changed;
         }
         }
 
 
-        /** @ignore */
+        /** @hidden */
         public _cacheFloat4(uniformName: string, x: number, y: number, z: number, w: number): boolean {
         public _cacheFloat4(uniformName: string, x: number, y: number, z: number, w: number): boolean {
             var cache = this._valueCache[uniformName];
             var cache = this._valueCache[uniformName];
             if (!cache) {
             if (!cache) {

+ 0 - 0
src/Materials/babylon.imageProcessingConfiguration.ts


Some files were not shown because too many files changed in this diff