Browse Source

Serializers

sebastien 6 năm trước cách đây
mục cha
commit
2727725ddf
86 tập tin đã thay đổi với 28272 bổ sung21457 xóa
  1. 0 2
      .gitignore
  2. 3667 3667
      Playground/babylon.d.txt
  3. 49 35
      Tools/Gulp/config.json
  4. 3679 3679
      dist/preview release/babylon.d.ts
  5. 3 2
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  6. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.js.map
  7. 3 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  8. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js.map
  9. 4 3
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  10. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js.map
  11. 4 3
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  12. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js.map
  13. 3 1
      dist/preview release/loaders/babylon.glTFFileLoader.js
  14. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js.map
  15. 3 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  16. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js.map
  17. 865 152
      dist/preview release/loaders/babylon.objFileLoader.js
  18. 1 1
      dist/preview release/loaders/babylon.objFileLoader.js.map
  19. 865 152
      dist/preview release/loaders/babylon.objFileLoader.min.js
  20. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js.map
  21. 3 3
      dist/preview release/loaders/babylon.stlFileLoader.js
  22. 1 1
      dist/preview release/loaders/babylon.stlFileLoader.js.map
  23. 3 3
      dist/preview release/loaders/babylon.stlFileLoader.min.js
  24. 1 1
      dist/preview release/loaders/babylon.stlFileLoader.min.js.map
  25. 1 1
      dist/preview release/loaders/babylonjs.loaders.d.ts
  26. 6 6
      dist/preview release/loaders/babylonjs.loaders.js
  27. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  28. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  29. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js.map
  30. 2 2
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  31. 3685 3541
      dist/preview release/serializers/babylon.glTF2Serializer.js
  32. 1 0
      dist/preview release/serializers/babylon.glTF2Serializer.js.map
  33. 3703 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  34. 1 0
      dist/preview release/serializers/babylon.glTF2Serializer.min.js.map
  35. 335 135
      dist/preview release/serializers/babylon.objSerializer.js
  36. 1 0
      dist/preview release/serializers/babylon.objSerializer.js.map
  37. 335 1
      dist/preview release/serializers/babylon.objSerializer.min.js
  38. 1 0
      dist/preview release/serializers/babylon.objSerializer.min.js.map
  39. 542 1012
      dist/preview release/serializers/babylonjs.serializers.d.ts
  40. 3900 3722
      dist/preview release/serializers/babylonjs.serializers.js
  41. 1 0
      dist/preview release/serializers/babylonjs.serializers.js.map
  42. 2 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  43. 1 0
      dist/preview release/serializers/babylonjs.serializers.min.js.map
  44. 1139 1018
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  45. 1 1
      dist/preview release/viewer/babylon.viewer.js
  46. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  47. 4 3
      loaders/legacy/legacy-glTF1FileLoader.ts
  48. 4 3
      loaders/legacy/legacy-glTF2FileLoader.ts
  49. 3 1
      loaders/legacy/legacy-glTFFileLoader.ts
  50. 4 4
      loaders/legacy/legacy-objFileLoader.ts
  51. 3 3
      loaders/legacy/legacy-stlFileLoader.ts
  52. 1 0
      loaders/src/OBJ/index.ts
  53. 981 0
      loaders/src/OBJ/objFileLoader.ts
  54. 1 1
      loaders/src/glTF/2.0/glTFLoaderExtension.ts
  55. 1 1
      loaders/src/glTF/2.0/glTFLoaderInterfaces.ts
  56. 5 5
      loaders/src/legacy.ts
  57. 19 0
      serializers/legacy/legacy-glTF2Serializer.ts
  58. 14 0
      serializers/legacy/legacy-objSerializer.ts
  59. 0 151
      serializers/src/OBJ/babylon.objSerializer.ts
  60. 1 0
      serializers/src/OBJ/index.ts
  61. 149 0
      serializers/src/OBJ/objSerializer.ts
  62. 100 100
      serializers/src/glTF/2.0/Extensions/KHR_texture_transform.ts
  63. 1 0
      serializers/src/glTF/2.0/Extensions/index.ts
  64. 0 782
      serializers/src/glTF/2.0/babylon.glTFAnimation.ts
  65. 0 64
      serializers/src/glTF/2.0/babylon.glTFData.ts
  66. 0 1562
      serializers/src/glTF/2.0/babylon.glTFExporter.ts
  67. 0 27
      serializers/src/glTF/2.0/babylon.glTFExporterExtension.ts
  68. 0 1275
      serializers/src/glTF/2.0/babylon.glTFMaterialExporter.ts
  69. 0 84
      serializers/src/glTF/2.0/babylon.glTFSerializer.ts
  70. 0 195
      serializers/src/glTF/2.0/babylon.glTFUtilities.ts
  71. 783 0
      serializers/src/glTF/2.0/glTFAnimation.ts
  72. 61 0
      serializers/src/glTF/2.0/glTFData.ts
  73. 1564 0
      serializers/src/glTF/2.0/glTFExporter.ts
  74. 32 0
      serializers/src/glTF/2.0/glTFExporterExtension.ts
  75. 1275 0
      serializers/src/glTF/2.0/glTFMaterialExporter.ts
  76. 84 0
      serializers/src/glTF/2.0/glTFSerializer.ts
  77. 194 0
      serializers/src/glTF/2.0/glTFUtilities.ts
  78. 7 0
      serializers/src/glTF/2.0/index.ts
  79. 0 23
      serializers/src/glTF/babylon.glTFFileExporter.ts
  80. 21 0
      serializers/src/glTF/glTFFileExporter.ts
  81. 2 0
      serializers/src/glTF/index.ts
  82. 2 0
      serializers/src/index.ts
  83. 19 0
      serializers/src/legacy.ts
  84. 0 13
      serializers/src/tsconfig.json
  85. 41 0
      serializers/tsconfig.json
  86. 74 0
      serializers/webpack.config.js

+ 0 - 2
.gitignore

@@ -1,6 +1,5 @@
 # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
 [Bb]in/
-[Oo]bj/
 
 # mstest test results
 TestResults
@@ -107,7 +106,6 @@ AppPackages/
 
 # Others
 [Bb]in
-[Oo]bj
 sql
 TestResults
 [Tt]est[Rr]esult*

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


+ 49 - 35
Tools/Gulp/config.json

@@ -1995,48 +1995,62 @@
     "serializers": {
         "libraries": [
             {
-                "files": [
-                    "../../serializers/src/OBJ/babylon.objSerializer.ts"
-                ],
-                "output": "babylon.objSerializer.js"
+                "files": [],
+                "noBundleInName": true,
+                "output": "babylonjs.serializers.min.js",
+                "webpack": "../../serializers/webpack.config.js",
+                "entry": "./src/legacy.ts",
+                "bundle": "true",
+                "babylonIncluded": false,
+                "useOutputForDebugging": true,
+                "isMain": true
             },
             {
-                "files": [
-                    "../../serializers/src/glTF/2.0/babylon.glTFSerializer.ts",
-                    "../../serializers/src/glTF/2.0/babylon.glTFExporter.ts",
-                    "../../serializers/src/glTF/2.0/babylon.glTFData.ts",
-                    "../../serializers/src/glTF/2.0/babylon.glTFMaterialExporter.ts",
-                    "../../serializers/src/glTF/2.0/babylon.glTFAnimation.ts",
-                    "../../serializers/src/glTF/2.0/babylon.glTFUtilities.ts",
-                    "../../serializers/src/glTF/2.0/babylon.glTFExporterExtension.ts",
-                    "../../serializers/src/glTF/babylon.glTFFileExporter.ts",
-                    "../../serializers/src/glTF/2.0/Extensions/KHR_texture_transform.ts"
-                ],
-                "excludeFromLoader": [
-                    "../../serializers/src/glTF/2.0/babylon.glTFExporterExtension.ts",
-                    "../../serializers/src/glTF/babylon.glTFFileExporter.ts"
-                ],
-                "shaderFiles": [
-                    "../../serializers/src/glTF/2.0/shaders/textureTransform.fragment.fx"
-                ],
-                "output": "babylon.glTF2Serializer.js"
+                "files": [],
+                "noBundleInName": true,
+                "output": "babylon.objSerializer.min.js",
+                "webpack": "../../serializers/webpack.config.js",
+                "entry": "./legacy/legacy-objSerializer.ts",
+                "bundle": "true",
+                "babylonIncluded": false,
+                "useOutputForDebugging": true,
+                "preventLoadLibrary": true
+            },
+            {
+                "files": [],
+                "noBundleInName": true,
+                "output": "babylon.glTF2Serializer.min.js",
+                "webpack": "../../serializers/webpack.config.js",
+                "entry": "./legacy/legacy-glTF2Serializer.ts",
+                "bundle": "true",
+                "babylonIncluded": false,
+                "useOutputForDebugging": true,
+                "preventLoadLibrary": true
             }
         ],
         "build": {
-            "srcOutputDirectory": "../../serializers/",
+            "webpack": "../../serializers/webpack.config.js",
+            "srcOutputDirectory": "../../serializers/src/",
             "distOutputDirectory": "/serializers/",
-            "buildAsModule": true,
-            "moduleName": "babylonjs-serializers",
-            "extraTypesDependencies": [
-                "babylonjs",
-                "babylonjs-gltf2interface"
-            ],
-            "outputFilename": "babylonjs.serializers",
-            "moduleDeclaration": {
-                "name": "Serializers",
-                "module": "babylonjs-serializers"
+            "dtsBundle": {
+                "name": "babylonjs-serializers",
+                "main": "../../dist/preview release/serializers/build/src/index.d.ts",
+                "out": "../babylonjs.serializers.module.d.ts",
+                "baseDir": "../../dist/preview release/serializers/build/",
+                "headerText": "BabylonJS serializers"
             },
-            "extendsRoot": true
+            "processDeclaration": {
+                "filename": "babylonjs.serializers.module.d.ts",
+                "packageName": "babylonjs-serializers",
+                "moduleName": "BABYLON",
+                "importsToRemove": [],
+                "classMap": {
+                    "babylonjs": "BABYLON",
+                    "babylonjs-loaders": "BABYLON",
+                    "babylonjs-serializers": "BABYLON",
+                    "babylonjs-gltf2interface": "BABYLON.GLTF2"
+                }
+            }
         }
     },
     "gui": {

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


+ 3 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -141,7 +141,7 @@ function __export(m) {
 }
 Object.defineProperty(exports, "__esModule", { value: true });
 var FileLoader = __webpack_require__(/*! ../src/glTF/glTFFileLoader */ "./src/glTF/glTFFileLoader.ts");
-var Loaders = __webpack_require__(/*! ../src/glTF/1.0 */ "./src/glTF/1.0/index.ts");
+var LoadersV1 = __webpack_require__(/*! ../src/glTF/1.0 */ "./src/glTF/1.0/index.ts");
 /**
  * This is the entry point for the UMD module.
  * The entry point for a future ESM package should be index.ts
@@ -151,11 +151,12 @@ if (typeof globalObject !== "undefined") {
     for (var key in FileLoader) {
         globalObject.BABYLON[key] = FileLoader[key];
     }
-    for (var key in Loaders) {
+    for (var key in LoadersV1) {
         globalObject.BABYLON[key] = FileLoader[key];
     }
 }
 __export(__webpack_require__(/*! ../src/glTF/glTFFileLoader */ "./src/glTF/glTFFileLoader.ts"));
+__export(__webpack_require__(/*! ../src/glTF/1.0 */ "./src/glTF/1.0/index.ts"));
 
 /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../node_modules/webpack/buildin/global.js */ "../node_modules/webpack/buildin/global.js")))
 

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


+ 3 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js

@@ -141,7 +141,7 @@ function __export(m) {
 }
 Object.defineProperty(exports, "__esModule", { value: true });
 var FileLoader = __webpack_require__(/*! ../src/glTF/glTFFileLoader */ "./src/glTF/glTFFileLoader.ts");
-var Loaders = __webpack_require__(/*! ../src/glTF/1.0 */ "./src/glTF/1.0/index.ts");
+var LoadersV1 = __webpack_require__(/*! ../src/glTF/1.0 */ "./src/glTF/1.0/index.ts");
 /**
  * This is the entry point for the UMD module.
  * The entry point for a future ESM package should be index.ts
@@ -151,11 +151,12 @@ if (typeof globalObject !== "undefined") {
     for (var key in FileLoader) {
         globalObject.BABYLON[key] = FileLoader[key];
     }
-    for (var key in Loaders) {
+    for (var key in LoadersV1) {
         globalObject.BABYLON[key] = FileLoader[key];
     }
 }
 __export(__webpack_require__(/*! ../src/glTF/glTFFileLoader */ "./src/glTF/glTFFileLoader.ts"));
+__export(__webpack_require__(/*! ../src/glTF/1.0 */ "./src/glTF/1.0/index.ts"));
 
 /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../node_modules/webpack/buildin/global.js */ "../node_modules/webpack/buildin/global.js")))
 

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


+ 4 - 3
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -141,7 +141,7 @@ function __export(m) {
 }
 Object.defineProperty(exports, "__esModule", { value: true });
 var FileLoader = __webpack_require__(/*! ../src/glTF/glTFFileLoader */ "./src/glTF/glTFFileLoader.ts");
-var Loaders = __webpack_require__(/*! ../src/glTF/2.0 */ "./src/glTF/2.0/index.ts");
+var LoadersV2 = __webpack_require__(/*! ../src/glTF/2.0 */ "./src/glTF/2.0/index.ts");
 /**
  * This is the entry point for the UMD module.
  * The entry point for a future ESM package should be index.ts
@@ -151,11 +151,12 @@ if (typeof globalObject !== "undefined") {
     for (var key in FileLoader) {
         globalObject.BABYLON[key] = FileLoader[key];
     }
-    for (var key in Loaders) {
+    for (var key in LoadersV2) {
         globalObject.BABYLON[key] = FileLoader[key];
     }
 }
 __export(__webpack_require__(/*! ../src/glTF/glTFFileLoader */ "./src/glTF/glTFFileLoader.ts"));
+__export(__webpack_require__(/*! ../src/glTF/2.0 */ "./src/glTF/2.0/index.ts"));
 
 /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../node_modules/webpack/buildin/global.js */ "../node_modules/webpack/buildin/global.js")))
 
@@ -3135,7 +3136,7 @@ glTFFileLoader_1.GLTFFileLoader._CreateGLTFLoaderV2 = function (parent) { return
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.tata = 0;
+exports.toto = 0;
 
 
 /***/ }),

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


+ 4 - 3
dist/preview release/loaders/babylon.glTF2FileLoader.min.js

@@ -141,7 +141,7 @@ function __export(m) {
 }
 Object.defineProperty(exports, "__esModule", { value: true });
 var FileLoader = __webpack_require__(/*! ../src/glTF/glTFFileLoader */ "./src/glTF/glTFFileLoader.ts");
-var Loaders = __webpack_require__(/*! ../src/glTF/2.0 */ "./src/glTF/2.0/index.ts");
+var LoadersV2 = __webpack_require__(/*! ../src/glTF/2.0 */ "./src/glTF/2.0/index.ts");
 /**
  * This is the entry point for the UMD module.
  * The entry point for a future ESM package should be index.ts
@@ -151,11 +151,12 @@ if (typeof globalObject !== "undefined") {
     for (var key in FileLoader) {
         globalObject.BABYLON[key] = FileLoader[key];
     }
-    for (var key in Loaders) {
+    for (var key in LoadersV2) {
         globalObject.BABYLON[key] = FileLoader[key];
     }
 }
 __export(__webpack_require__(/*! ../src/glTF/glTFFileLoader */ "./src/glTF/glTFFileLoader.ts"));
+__export(__webpack_require__(/*! ../src/glTF/2.0 */ "./src/glTF/2.0/index.ts"));
 
 /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../node_modules/webpack/buildin/global.js */ "../node_modules/webpack/buildin/global.js")))
 
@@ -3135,7 +3136,7 @@ glTFFileLoader_1.GLTFFileLoader._CreateGLTFLoaderV2 = function (parent) { return
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.tata = 0;
+exports.toto = 0;
 
 
 /***/ }),

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


+ 3 - 1
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -160,6 +160,8 @@ if (typeof globalObject !== "undefined") {
     }
 }
 __export(__webpack_require__(/*! ../src/glTF/glTFFileLoader */ "./src/glTF/glTFFileLoader.ts"));
+__export(__webpack_require__(/*! ../src/glTF/1.0 */ "./src/glTF/1.0/index.ts"));
+__export(__webpack_require__(/*! ../src/glTF/2.0 */ "./src/glTF/2.0/index.ts"));
 
 /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../node_modules/webpack/buildin/global.js */ "../node_modules/webpack/buildin/global.js")))
 
@@ -5410,7 +5412,7 @@ glTFFileLoader_1.GLTFFileLoader._CreateGLTFLoaderV2 = function (parent) { return
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.tata = 0;
+exports.toto = 0;
 
 
 /***/ }),

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


+ 3 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js

@@ -160,6 +160,8 @@ if (typeof globalObject !== "undefined") {
     }
 }
 __export(__webpack_require__(/*! ../src/glTF/glTFFileLoader */ "./src/glTF/glTFFileLoader.ts"));
+__export(__webpack_require__(/*! ../src/glTF/1.0 */ "./src/glTF/1.0/index.ts"));
+__export(__webpack_require__(/*! ../src/glTF/2.0 */ "./src/glTF/2.0/index.ts"));
 
 /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../node_modules/webpack/buildin/global.js */ "../node_modules/webpack/buildin/global.js")))
 
@@ -5410,7 +5412,7 @@ glTFFileLoader_1.GLTFFileLoader._CreateGLTFLoaderV2 = function (parent) { return
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.tata = 0;
+exports.toto = 0;
 
 
 /***/ }),

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


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


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


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


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


+ 3 - 3
dist/preview release/loaders/babylon.stlFileLoader.js

@@ -140,15 +140,15 @@ function __export(m) {
     for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
 }
 Object.defineProperty(exports, "__esModule", { value: true });
-var MatLib = __webpack_require__(/*! ../src/STL */ "./src/STL/index.ts");
+var Loaders = __webpack_require__(/*! ../src/STL */ "./src/STL/index.ts");
 /**
  * This is the entry point for the UMD module.
  * The entry point for a future ESM package should be index.ts
  */
 var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : undefined);
 if (typeof globalObject !== "undefined") {
-    for (var key in MatLib) {
-        globalObject.BABYLON[key] = MatLib[key];
+    for (var key in Loaders) {
+        globalObject.BABYLON[key] = Loaders[key];
     }
 }
 __export(__webpack_require__(/*! ../src/STL */ "./src/STL/index.ts"));

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


+ 3 - 3
dist/preview release/loaders/babylon.stlFileLoader.min.js

@@ -140,15 +140,15 @@ function __export(m) {
     for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
 }
 Object.defineProperty(exports, "__esModule", { value: true });
-var MatLib = __webpack_require__(/*! ../src/STL */ "./src/STL/index.ts");
+var Loaders = __webpack_require__(/*! ../src/STL */ "./src/STL/index.ts");
 /**
  * This is the entry point for the UMD module.
  * The entry point for a future ESM package should be index.ts
  */
 var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : undefined);
 if (typeof globalObject !== "undefined") {
-    for (var key in MatLib) {
-        globalObject.BABYLON[key] = MatLib[key];
+    for (var key in Loaders) {
+        globalObject.BABYLON[key] = Loaders[key];
     }
 }
 __export(__webpack_require__(/*! ../src/STL */ "./src/STL/index.ts"));

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


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

@@ -772,7 +772,7 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
-    export var tata: number;
+    export var toto: number;
     /**
         * Interface for a glTF loader extension.
         */

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

@@ -6485,7 +6485,7 @@ glTFFileLoader_1.GLTFFileLoader._CreateGLTFLoaderV2 = function (parent) { return
 "use strict";
 
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.tata = 0;
+exports.toto = 0;
 
 
 /***/ }),
@@ -7321,9 +7321,9 @@ function __export(m) {
     for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
 }
 Object.defineProperty(exports, "__esModule", { value: true });
-var MatLib = __webpack_require__(/*! ./index */ "./src/index.ts");
+var Loaders = __webpack_require__(/*! ./index */ "./src/index.ts");
 /**
- * Legacy support, defining window.BABYLON.GridMaterial... (global variable).
+ * Legacy support, defining window.BABYLON.OBJLoader... (global variable).
  *
  * This is the entry point for the UMD module.
  * The entry point for a future ESM package should be index.ts
@@ -7331,9 +7331,9 @@ var MatLib = __webpack_require__(/*! ./index */ "./src/index.ts");
 var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : undefined);
 if (typeof globalObject !== "undefined") {
     globalObject.BABYLON = globalObject.BABYLON || {};
-    for (var mat in MatLib) {
-        if (MatLib.hasOwnProperty(mat)) {
-            globalObject.BABYLON[mat] = MatLib[mat];
+    for (var loader in Loaders) {
+        if (Loaders.hasOwnProperty(loader)) {
+            globalObject.BABYLON[loader] = Loaders[loader];
         }
     }
 }

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


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


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


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

@@ -844,7 +844,7 @@ declare module 'babylonjs-loaders/src/glTF/2.0/glTFLoaderExtension' {
     import { IDisposable, Nullable, Mesh, Camera, Geometry, Material, BaseTexture, AnimationGroup } from "babylonjs";
     import { ISceneV2, INodeV2, ICameraV2, IMeshPrimitiveV2, IMaterialV2, ITextureInfoV2, IAnimationV2 } from "babylonjs-loaders/src/glTF/2.0/glTFLoaderInterfaces";
     import { IGLTFLoaderExtension } from "babylonjs-loaders/src/glTF/glTFFileLoader";
-    export var tata: number;
+    export var toto: number;
     /**
         * Interface for a glTF loader extension.
         */
@@ -2531,7 +2531,7 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
-    export var tata: number;
+    export var toto: number;
     /**
         * Interface for a glTF loader extension.
         */

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


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


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


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


+ 335 - 135
dist/preview release/serializers/babylon.objSerializer.js

@@ -1,135 +1,335 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-var BABYLON;
-(function (BABYLON) {
-    var OBJExport = /** @class */ (function () {
-        function OBJExport() {
-        }
-        //Exports the geometry of a Mesh array in .OBJ file format (text)
-        OBJExport.OBJ = function (mesh, materials, matlibname, globalposition) {
-            var output = [];
-            var v = 1;
-            if (materials) {
-                if (!matlibname) {
-                    matlibname = 'mat';
-                }
-                output.push("mtllib " + matlibname + ".mtl");
-            }
-            for (var j = 0; j < mesh.length; j++) {
-                output.push("g object" + j);
-                output.push("o object_" + j);
-                //Uses the position of the item in the scene, to the file (this back to normal in the end)
-                var lastMatrix = null;
-                if (globalposition) {
-                    var newMatrix = BABYLON.Matrix.Translation(mesh[j].position.x, mesh[j].position.y, mesh[j].position.z);
-                    lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
-                    mesh[j].bakeTransformIntoVertices(newMatrix);
-                }
-                //TODO: submeshes (groups)
-                //TODO: smoothing groups (s 1, s off);
-                if (materials) {
-                    var mat = mesh[j].material;
-                    if (mat) {
-                        output.push("usemtl " + mat.id);
-                    }
-                }
-                var g = mesh[j].geometry;
-                if (!g) {
-                    BABYLON.Tools.Warn("No geometry is present on the mesh");
-                    continue;
-                }
-                var trunkVerts = g.getVerticesData('position');
-                var trunkNormals = g.getVerticesData('normal');
-                var trunkUV = g.getVerticesData('uv');
-                var trunkFaces = g.getIndices();
-                var curV = 0;
-                if (!trunkVerts || !trunkFaces) {
-                    BABYLON.Tools.Warn("There are no position vertices or indices on the mesh!");
-                    continue;
-                }
-                for (var i = 0; i < trunkVerts.length; i += 3) {
-                    output.push("v " + trunkVerts[i] + " " + trunkVerts[i + 1] + " " + trunkVerts[i + 2]);
-                    curV++;
-                }
-                if (trunkNormals != null) {
-                    for (i = 0; i < trunkNormals.length; i += 3) {
-                        output.push("vn " + trunkNormals[i] + " " + trunkNormals[i + 1] + " " + trunkNormals[i + 2]);
-                    }
-                }
-                if (trunkUV != null) {
-                    for (i = 0; i < trunkUV.length; i += 2) {
-                        output.push("vt " + trunkUV[i] + " " + trunkUV[i + 1]);
-                    }
-                }
-                for (i = 0; i < trunkFaces.length; i += 3) {
-                    var indices = [String(trunkFaces[i + 2] + v), String(trunkFaces[i + 1] + v), String(trunkFaces[i] + v)];
-                    var blanks = ["", "", ""];
-                    var facePositions = indices;
-                    var faceUVs = trunkUV != null ? indices : blanks;
-                    var faceNormals = trunkNormals != null ? indices : blanks;
-                    output.push("f " + facePositions[0] + "/" + faceUVs[0] + "/" + faceNormals[0] +
-                        " " + facePositions[1] + "/" + faceUVs[1] + "/" + faceNormals[1] +
-                        " " + facePositions[2] + "/" + faceUVs[2] + "/" + faceNormals[2]);
-                }
-                //back de previous matrix, to not change the original mesh in the scene
-                if (globalposition && lastMatrix) {
-                    mesh[j].bakeTransformIntoVertices(lastMatrix);
-                }
-                v += curV;
-            }
-            var text = output.join("\n");
-            return (text);
-        };
-        //Exports the material(s) of a mesh in .MTL file format (text)
-        //TODO: Export the materials of mesh array
-        OBJExport.MTL = function (mesh) {
-            var output = [];
-            var m = mesh.material;
-            output.push("newmtl mat1");
-            output.push("  Ns " + m.specularPower.toFixed(4));
-            output.push("  Ni 1.5000");
-            output.push("  d " + m.alpha.toFixed(4));
-            output.push("  Tr 0.0000");
-            output.push("  Tf 1.0000 1.0000 1.0000");
-            output.push("  illum 2");
-            output.push("  Ka " + m.ambientColor.r.toFixed(4) + " " + m.ambientColor.g.toFixed(4) + " " + m.ambientColor.b.toFixed(4));
-            output.push("  Kd " + m.diffuseColor.r.toFixed(4) + " " + m.diffuseColor.g.toFixed(4) + " " + m.diffuseColor.b.toFixed(4));
-            output.push("  Ks " + m.specularColor.r.toFixed(4) + " " + m.specularColor.g.toFixed(4) + " " + m.specularColor.b.toFixed(4));
-            output.push("  Ke " + m.emissiveColor.r.toFixed(4) + " " + m.emissiveColor.g.toFixed(4) + " " + m.emissiveColor.b.toFixed(4));
-            //TODO: uv scale, offset, wrap
-            //TODO: UV mirrored in Blender? second UV channel? lightMap? reflection textures?
-            var uvscale = "";
-            if (m.ambientTexture) {
-                output.push("  map_Ka " + uvscale + m.ambientTexture.name);
-            }
-            if (m.diffuseTexture) {
-                output.push("  map_Kd " + uvscale + m.diffuseTexture.name);
-                //TODO: alpha testing, opacity in diffuse texture alpha channel (diffuseTexture.hasAlpha -> map_d)
-            }
-            if (m.specularTexture) {
-                output.push("  map_Ks " + uvscale + m.specularTexture.name);
-                /* TODO: glossiness = specular highlight component is in alpha channel of specularTexture. (???)
-                if (m.useGlossinessFromSpecularMapAlpha)  {
-                    output.push("  map_Ns "+uvscale + m.specularTexture.name);
-                }
-                */
-            }
-            /* TODO: emissive texture not in .MAT format (???)
-            if (m.emissiveTexture) {
-                output.push("  map_d "+uvscale+m.emissiveTexture.name);
-            }
-            */
-            if (m.bumpTexture) {
-                output.push("  map_bump -imfchan z " + uvscale + m.bumpTexture.name);
-            }
-            if (m.opacityTexture) {
-                output.push("  map_d " + uvscale + m.opacityTexture.name);
-            }
-            var text = output.join("\n");
-            return (text);
-        };
-        return OBJExport;
-    }());
-    BABYLON.OBJExport = OBJExport;
-})(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=babylon.objSerializer.js.map
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory(require("babylonjs"));
+	else if(typeof define === 'function' && define.amd)
+		define("babylonjs-serializers", ["babylonjs"], factory);
+	else if(typeof exports === 'object')
+		exports["babylonjs-serializers"] = factory(require("babylonjs"));
+	else
+		root["SERIALIZERS"] = factory(root["BABYLON"]);
+})(window, function(__WEBPACK_EXTERNAL_MODULE_babylonjs__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__webpack_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__webpack_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __webpack_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__webpack_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = "./legacy/legacy-objSerializer.ts");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "../node_modules/webpack/buildin/global.js":
+/*!*************************************************!*\
+  !*** ../node_modules/webpack/buildin/global.js ***!
+  \*************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+var g;
+
+// This works in non-strict mode
+g = (function() {
+	return this;
+})();
+
+try {
+	// This works if eval is allowed (see CSP)
+	g = g || Function("return this")() || (1, eval)("this");
+} catch (e) {
+	// This works if the window reference is available
+	if (typeof window === "object") g = window;
+}
+
+// g can still be undefined, but nothing to do about it...
+// We return undefined, instead of nothing here, so it's
+// easier to handle this case. if(!global) { ...}
+
+module.exports = g;
+
+
+/***/ }),
+
+/***/ "./legacy/legacy-objSerializer.ts":
+/*!****************************************!*\
+  !*** ./legacy/legacy-objSerializer.ts ***!
+  \****************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/* WEBPACK VAR INJECTION */(function(global) {
+function __export(m) {
+    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+Object.defineProperty(exports, "__esModule", { value: true });
+var Serializers = __webpack_require__(/*! ../src/OBJ */ "./src/OBJ/index.ts");
+/**
+ * This is the entry point for the UMD module.
+ * The entry point for a future ESM package should be index.ts
+ */
+var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : undefined);
+if (typeof globalObject !== "undefined") {
+    for (var serializer in Serializers) {
+        globalObject.BABYLON[serializer] = Serializers[serializer];
+    }
+}
+__export(__webpack_require__(/*! ../src/OBJ */ "./src/OBJ/index.ts"));
+
+/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../node_modules/webpack/buildin/global.js */ "../node_modules/webpack/buildin/global.js")))
+
+/***/ }),
+
+/***/ "./src/OBJ/index.ts":
+/*!**************************!*\
+  !*** ./src/OBJ/index.ts ***!
+  \**************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+function __export(m) {
+    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+Object.defineProperty(exports, "__esModule", { value: true });
+__export(__webpack_require__(/*! ./objSerializer */ "./src/OBJ/objSerializer.ts"));
+
+
+/***/ }),
+
+/***/ "./src/OBJ/objSerializer.ts":
+/*!**********************************!*\
+  !*** ./src/OBJ/objSerializer.ts ***!
+  \**********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+Object.defineProperty(exports, "__esModule", { value: true });
+var babylonjs_1 = __webpack_require__(/*! babylonjs */ "babylonjs");
+var OBJExport = /** @class */ (function () {
+    function OBJExport() {
+    }
+    //Exports the geometry of a Mesh array in .OBJ file format (text)
+    OBJExport.OBJ = function (mesh, materials, matlibname, globalposition) {
+        var output = [];
+        var v = 1;
+        if (materials) {
+            if (!matlibname) {
+                matlibname = 'mat';
+            }
+            output.push("mtllib " + matlibname + ".mtl");
+        }
+        for (var j = 0; j < mesh.length; j++) {
+            output.push("g object" + j);
+            output.push("o object_" + j);
+            //Uses the position of the item in the scene, to the file (this back to normal in the end)
+            var lastMatrix = null;
+            if (globalposition) {
+                var newMatrix = BABYLON.Matrix.Translation(mesh[j].position.x, mesh[j].position.y, mesh[j].position.z);
+                lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
+                mesh[j].bakeTransformIntoVertices(newMatrix);
+            }
+            //TODO: submeshes (groups)
+            //TODO: smoothing groups (s 1, s off);
+            if (materials) {
+                var mat = mesh[j].material;
+                if (mat) {
+                    output.push("usemtl " + mat.id);
+                }
+            }
+            var g = mesh[j].geometry;
+            if (!g) {
+                babylonjs_1.Tools.Warn("No geometry is present on the mesh");
+                continue;
+            }
+            var trunkVerts = g.getVerticesData('position');
+            var trunkNormals = g.getVerticesData('normal');
+            var trunkUV = g.getVerticesData('uv');
+            var trunkFaces = g.getIndices();
+            var curV = 0;
+            if (!trunkVerts || !trunkFaces) {
+                babylonjs_1.Tools.Warn("There are no position vertices or indices on the mesh!");
+                continue;
+            }
+            for (var i = 0; i < trunkVerts.length; i += 3) {
+                output.push("v " + trunkVerts[i] + " " + trunkVerts[i + 1] + " " + trunkVerts[i + 2]);
+                curV++;
+            }
+            if (trunkNormals != null) {
+                for (i = 0; i < trunkNormals.length; i += 3) {
+                    output.push("vn " + trunkNormals[i] + " " + trunkNormals[i + 1] + " " + trunkNormals[i + 2]);
+                }
+            }
+            if (trunkUV != null) {
+                for (i = 0; i < trunkUV.length; i += 2) {
+                    output.push("vt " + trunkUV[i] + " " + trunkUV[i + 1]);
+                }
+            }
+            for (i = 0; i < trunkFaces.length; i += 3) {
+                var indices = [String(trunkFaces[i + 2] + v), String(trunkFaces[i + 1] + v), String(trunkFaces[i] + v)];
+                var blanks = ["", "", ""];
+                var facePositions = indices;
+                var faceUVs = trunkUV != null ? indices : blanks;
+                var faceNormals = trunkNormals != null ? indices : blanks;
+                output.push("f " + facePositions[0] + "/" + faceUVs[0] + "/" + faceNormals[0] +
+                    " " + facePositions[1] + "/" + faceUVs[1] + "/" + faceNormals[1] +
+                    " " + facePositions[2] + "/" + faceUVs[2] + "/" + faceNormals[2]);
+            }
+            //back de previous matrix, to not change the original mesh in the scene
+            if (globalposition && lastMatrix) {
+                mesh[j].bakeTransformIntoVertices(lastMatrix);
+            }
+            v += curV;
+        }
+        var text = output.join("\n");
+        return (text);
+    };
+    //Exports the material(s) of a mesh in .MTL file format (text)
+    //TODO: Export the materials of mesh array
+    OBJExport.MTL = function (mesh) {
+        var output = [];
+        var m = mesh.material;
+        output.push("newmtl mat1");
+        output.push("  Ns " + m.specularPower.toFixed(4));
+        output.push("  Ni 1.5000");
+        output.push("  d " + m.alpha.toFixed(4));
+        output.push("  Tr 0.0000");
+        output.push("  Tf 1.0000 1.0000 1.0000");
+        output.push("  illum 2");
+        output.push("  Ka " + m.ambientColor.r.toFixed(4) + " " + m.ambientColor.g.toFixed(4) + " " + m.ambientColor.b.toFixed(4));
+        output.push("  Kd " + m.diffuseColor.r.toFixed(4) + " " + m.diffuseColor.g.toFixed(4) + " " + m.diffuseColor.b.toFixed(4));
+        output.push("  Ks " + m.specularColor.r.toFixed(4) + " " + m.specularColor.g.toFixed(4) + " " + m.specularColor.b.toFixed(4));
+        output.push("  Ke " + m.emissiveColor.r.toFixed(4) + " " + m.emissiveColor.g.toFixed(4) + " " + m.emissiveColor.b.toFixed(4));
+        //TODO: uv scale, offset, wrap
+        //TODO: UV mirrored in Blender? second UV channel? lightMap? reflection textures?
+        var uvscale = "";
+        if (m.ambientTexture) {
+            output.push("  map_Ka " + uvscale + m.ambientTexture.name);
+        }
+        if (m.diffuseTexture) {
+            output.push("  map_Kd " + uvscale + m.diffuseTexture.name);
+            //TODO: alpha testing, opacity in diffuse texture alpha channel (diffuseTexture.hasAlpha -> map_d)
+        }
+        if (m.specularTexture) {
+            output.push("  map_Ks " + uvscale + m.specularTexture.name);
+            /* TODO: glossiness = specular highlight component is in alpha channel of specularTexture. (???)
+            if (m.useGlossinessFromSpecularMapAlpha)  {
+                output.push("  map_Ns "+uvscale + m.specularTexture.name);
+            }
+            */
+        }
+        /* TODO: emissive texture not in .MAT format (???)
+        if (m.emissiveTexture) {
+            output.push("  map_d "+uvscale+m.emissiveTexture.name);
+        }
+        */
+        if (m.bumpTexture) {
+            output.push("  map_bump -imfchan z " + uvscale + m.bumpTexture.name);
+        }
+        if (m.opacityTexture) {
+            output.push("  map_d " + uvscale + m.opacityTexture.name);
+        }
+        var text = output.join("\n");
+        return (text);
+    };
+    return OBJExport;
+}());
+exports.OBJExport = OBJExport;
+
+
+/***/ }),
+
+/***/ "babylonjs":
+/*!****************************************************************************************************!*\
+  !*** external {"root":"BABYLON","commonjs":"babylonjs","commonjs2":"babylonjs","amd":"babylonjs"} ***!
+  \****************************************************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs__;
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=babylon.objSerializer.js.map

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


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


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


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


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


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


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


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


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1139 - 1018
dist/preview release/serializers/babylonjs.serializers.module.d.ts


+ 1 - 1
dist/preview release/viewer/babylon.viewer.js

@@ -116,7 +116,7 @@ var BabylonViewer=function(e){var t={};function i(r){if(t[r])return t[r].exports
 /*!*********************************************!*\
   !*** ./src/glTF/2.0/glTFLoaderExtension.ts ***!
   \*********************************************/
-/*! no static exports found */function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.tata=0},"./src/glTF/2.0/index.ts":
+/*! no static exports found */function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.toto=0},"./src/glTF/2.0/index.ts":
 /*!*******************************!*\
   !*** ./src/glTF/2.0/index.ts ***!
   \*******************************/

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


+ 4 - 3
loaders/legacy/legacy-glTF1FileLoader.ts

@@ -1,5 +1,5 @@
 import * as FileLoader from "../src/glTF/glTFFileLoader";
-import * as Loaders from "../src/glTF/1.0";
+import * as LoadersV1 from "../src/glTF/1.0";
 
 /**
  * This is the entry point for the UMD module.
@@ -10,9 +10,10 @@ if (typeof globalObject !== "undefined") {
     for (var key in FileLoader) {
         (<any>globalObject).BABYLON[key] = (<any>FileLoader)[key];
     }
-    for (var key in Loaders) {
+    for (var key in LoadersV1) {
         (<any>globalObject).BABYLON[key] = (<any>FileLoader)[key];
     }
 }
 
-export * from "../src/glTF/glTFFileLoader";
+export * from "../src/glTF/glTFFileLoader";
+export * from "../src/glTF/1.0";

+ 4 - 3
loaders/legacy/legacy-glTF2FileLoader.ts

@@ -1,5 +1,5 @@
 import * as FileLoader from "../src/glTF/glTFFileLoader";
-import * as Loaders from "../src/glTF/2.0";
+import * as LoadersV2 from "../src/glTF/2.0";
 
 /**
  * This is the entry point for the UMD module.
@@ -10,9 +10,10 @@ if (typeof globalObject !== "undefined") {
     for (var key in FileLoader) {
         (<any>globalObject).BABYLON[key] = (<any>FileLoader)[key];
     }
-    for (var key in Loaders) {
+    for (var key in LoadersV2) {
         (<any>globalObject).BABYLON[key] = (<any>FileLoader)[key];
     }
 }
 
-export * from "../src/glTF/glTFFileLoader";
+export * from "../src/glTF/glTFFileLoader";
+export * from "../src/glTF/2.0";

+ 3 - 1
loaders/legacy/legacy-glTFFileLoader.ts

@@ -19,4 +19,6 @@ if (typeof globalObject !== "undefined") {
     }
 }
 
-export * from "../src/glTF/glTFFileLoader";
+export * from "../src/glTF/glTFFileLoader";
+export * from "../src/glTF/1.0";
+export * from "../src/glTF/2.0";

+ 4 - 4
loaders/legacy/legacy-objFileLoader.ts

@@ -1,4 +1,4 @@
-import * as MatLib from "../src/STL";
+import * as Loaders from "../src/OBJ";
 
 /**
  * This is the entry point for the UMD module.
@@ -6,9 +6,9 @@ import * as MatLib from "../src/STL";
  */
 var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : undefined);
 if (typeof globalObject !== "undefined") {
-    for (var key in MatLib) {
-        (<any>globalObject).BABYLON[key] = (<any>MatLib)[key];
+    for (var key in Loaders) {
+        (<any>globalObject).BABYLON[key] = (<any>Loaders)[key];
     }
 }
 
-export * from "../src/STL";
+export * from "../src/OBJ";

+ 3 - 3
loaders/legacy/legacy-stlFileLoader.ts

@@ -1,4 +1,4 @@
-import * as MatLib from "../src/STL";
+import * as Loaders from "../src/STL";
 
 /**
  * This is the entry point for the UMD module.
@@ -6,8 +6,8 @@ import * as MatLib from "../src/STL";
  */
 var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : undefined);
 if (typeof globalObject !== "undefined") {
-    for (var key in MatLib) {
-        (<any>globalObject).BABYLON[key] = (<any>MatLib)[key];
+    for (var key in Loaders) {
+        (<any>globalObject).BABYLON[key] = (<any>Loaders)[key];
     }
 }
 

+ 1 - 0
loaders/src/OBJ/index.ts

@@ -0,0 +1 @@
+export * from "./objFileLoader";

+ 981 - 0
loaders/src/OBJ/objFileLoader.ts

@@ -0,0 +1,981 @@
+import { Geometry, Mesh, SceneLoader, Vector3, Vector2, Tools, Color3, StandardMaterial, Nullable, Scene, Texture, ISceneLoaderPluginAsync, SceneLoaderProgressEvent, AbstractMesh, IParticleSystem, Skeleton, AnimationGroup, AssetContainer, VertexData } from "babylonjs";
+
+/**
+ * Class reading and parsing the MTL file bundled with the obj file.
+ */
+export class MTLFileLoader {
+
+    // All material loaded from the mtl will be set here
+    public materials: StandardMaterial[] = [];
+
+    /**
+     * This function will read the mtl file and create each material described inside
+     * This function could be improve by adding :
+     * -some component missing (Ni, Tf...)
+     * -including the specific options available
+     *
+     * @param scene
+     * @param data
+     * @param rootUrl
+     */
+    public parseMTL(scene: Scene, data: string | ArrayBuffer, rootUrl: string) {
+        if (data instanceof ArrayBuffer) {
+            return;
+        }
+
+        //Split the lines from the file
+        var lines = data.split('\n');
+        //Space char
+        var delimiter_pattern = /\s+/;
+        //Array with RGB colors
+        var color: number[];
+        //New material
+        var material: Nullable<StandardMaterial> = null;
+
+        //Look at each line
+        for (var i = 0; i < lines.length; i++) {
+            var line = lines[i].trim();
+
+            // Blank line or comment
+            if (line.length === 0 || line.charAt(0) === '#') {
+                continue;
+            }
+
+            //Get the first parameter (keyword)
+            var pos = line.indexOf(' ');
+            var key = (pos >= 0) ? line.substring(0, pos) : line;
+            key = key.toLowerCase();
+
+            //Get the data following the key
+            var value: string = (pos >= 0) ? line.substring(pos + 1).trim() : "";
+
+            //This mtl keyword will create the new material
+            if (key === "newmtl") {
+                //Check if it is the first material.
+                // Materials specifications are described after this keyword.
+                if (material) {
+                    //Add the previous material in the material array.
+                    this.materials.push(material);
+                }
+                //Create a new material.
+                // value is the name of the material read in the mtl file
+                material = new StandardMaterial(value, scene);
+            } else if (key === "kd" && material) {
+                // Diffuse color (color under white light) using RGB values
+
+                //value  = "r g b"
+                color = <number[]>value.split(delimiter_pattern, 3).map(parseFloat);
+                //color = [r,g,b]
+                //Set tghe color into the material
+                material.diffuseColor = Color3.FromArray(color);
+            } else if (key === "ka" && material) {
+                // Ambient color (color under shadow) using RGB values
+
+                //value = "r g b"
+                color = <number[]>value.split(delimiter_pattern, 3).map(parseFloat);
+                //color = [r,g,b]
+                //Set tghe color into the material
+                material.ambientColor = Color3.FromArray(color);
+            } else if (key === "ks" && material) {
+                // Specular color (color when light is reflected from shiny surface) using RGB values
+
+                //value = "r g b"
+                color = <number[]>value.split(delimiter_pattern, 3).map(parseFloat);
+                //color = [r,g,b]
+                //Set the color into the material
+                material.specularColor = Color3.FromArray(color);
+            } else if (key === "ke" && material) {
+                // Emissive color using RGB values
+                color = value.split(delimiter_pattern, 3).map(parseFloat);
+                material.emissiveColor = Color3.FromArray(color);
+            } else if (key === "ns" && material) {
+
+                //value = "Integer"
+                material.specularPower = parseFloat(value);
+            } else if (key === "d" && material) {
+                //d is dissolve for current material. It mean alpha for BABYLON
+                material.alpha = parseFloat(value);
+
+                //Texture
+                //This part can be improved by adding the possible options of texture
+            } else if (key === "map_ka" && material) {
+                // ambient texture map with a loaded image
+                //We must first get the folder of the image
+                material.ambientTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
+            } else if (key === "map_kd" && material) {
+                // Diffuse texture map with a loaded image
+                material.diffuseTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
+            } else if (key === "map_ks" && material) {
+                // Specular texture map with a loaded image
+                //We must first get the folder of the image
+                material.specularTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
+            } else if (key === "map_ns") {
+                //Specular
+                //Specular highlight component
+                //We must first get the folder of the image
+                //
+                //Not supported by BABYLON
+                //
+                //    continue;
+            } else if (key === "map_bump" && material) {
+                //The bump texture
+                material.bumpTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
+            } else if (key === "map_d" && material) {
+                // The dissolve of the material
+                material.opacityTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
+
+                //Options for illumination
+            } else if (key === "illum") {
+                //Illumination
+                if (value === "0") {
+                    //That mean Kd == Kd
+                } else if (value === "1") {
+                    //Color on and Ambient on
+                } else if (value === "2") {
+                    //Highlight on
+                } else if (value === "3") {
+                    //Reflection on and Ray trace on
+                } else if (value === "4") {
+                    //Transparency: Glass on, Reflection: Ray trace on
+                } else if (value === "5") {
+                    //Reflection: Fresnel on and Ray trace on
+                } else if (value === "6") {
+                    //Transparency: Refraction on, Reflection: Fresnel off and Ray trace on
+                } else if (value === "7") {
+                    //Transparency: Refraction on, Reflection: Fresnel on and Ray trace on
+                } else if (value === "8") {
+                    //Reflection on and Ray trace off
+                } else if (value === "9") {
+                    //Transparency: Glass on, Reflection: Ray trace off
+                } else if (value === "10") {
+                    //Casts shadows onto invisible surfaces
+                }
+            } else {
+                // console.log("Unhandled expression at line : " + i +'\n' + "with value : " + line);
+            }
+        }
+        //At the end of the file, add the last material
+        if (material) {
+            this.materials.push(material);
+        }
+    }
+
+    /**
+     * Gets the texture for the material.
+     *
+     * If the material is imported from input file,
+     * We sanitize the url to ensure it takes the textre from aside the material.
+     *
+     * @param rootUrl The root url to load from
+     * @param value The value stored in the mtl
+     * @return The Texture
+     */
+    private static _getTexture(rootUrl: string, value: string, scene: Scene): Nullable<Texture> {
+        if (!value) {
+            return null;
+        }
+
+        var url = rootUrl;
+        // Load from input file.
+        if (rootUrl === "file:") {
+            var lastDelimiter = value.lastIndexOf("\\");
+            if (lastDelimiter === -1) {
+                lastDelimiter = value.lastIndexOf("/");
+            }
+
+            if (lastDelimiter > -1) {
+                url += value.substr(lastDelimiter + 1);
+            }
+            else {
+                url += value;
+            }
+        }
+        // Not from input file.
+        else {
+            url += value;
+        }
+
+        return new Texture(url, scene);
+    }
+}
+
+export class OBJFileLoader implements ISceneLoaderPluginAsync {
+
+    public static OPTIMIZE_WITH_UV = false;
+    public static INVERT_Y = false;
+    public name = "obj";
+    public extensions = ".obj";
+    public obj = /^o/;
+    public group = /^g/;
+    public mtllib = /^mtllib /;
+    public usemtl = /^usemtl /;
+    public smooth = /^s /;
+    public vertexPattern = /v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/;
+    // vn float float float
+    public normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/;
+    // vt float float
+    public uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/;
+    // f vertex vertex vertex ...
+    public facePattern1 = /f\s+(([\d]{1,}[\s]?){3,})+/;
+    // f vertex/uvs vertex/uvs vertex/uvs ...
+    public facePattern2 = /f\s+((([\d]{1,}\/[\d]{1,}[\s]?){3,})+)/;
+    // f vertex/uvs/normal vertex/uvs/normal vertex/uvs/normal ...
+    public facePattern3 = /f\s+((([\d]{1,}\/[\d]{1,}\/[\d]{1,}[\s]?){3,})+)/;
+    // f vertex//normal vertex//normal vertex//normal ...
+    public facePattern4 = /f\s+((([\d]{1,}\/\/[\d]{1,}[\s]?){3,})+)/;
+    // f -vertex/-uvs/-normal -vertex/-uvs/-normal -vertex/-uvs/-normal ...
+    public facePattern5 = /f\s+(((-[\d]{1,}\/-[\d]{1,}\/-[\d]{1,}[\s]?){3,})+)/;
+
+    /**
+     * Calls synchronously the MTL file attached to this obj.
+     * Load function or importMesh function don't enable to load 2 files in the same time asynchronously.
+     * Without this function materials are not displayed in the first frame (but displayed after).
+     * In consequence it is impossible to get material information in your HTML file
+     *
+     * @param url The URL of the MTL file
+     * @param rootUrl
+     * @param onSuccess Callback function to be called when the MTL file is loaded
+     * @private
+     */
+    private _loadMTL(url: string, rootUrl: string, onSuccess: (response: string | ArrayBuffer, responseUrl?: string) => any) {
+        //The complete path to the mtl file
+        var pathOfFile = Tools.BaseUrl + rootUrl + url;
+
+        // Loads through the babylon tools to allow fileInput search.
+        Tools.LoadFile(pathOfFile,
+            onSuccess,
+            undefined,
+            undefined,
+            false,
+            () => { console.warn("Error - Unable to load " + pathOfFile); });
+    }
+
+    /**
+     * 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
+     * @param fileName Defines the name of the file to load
+     * @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, fileName?: string): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
+        //get the meshes from OBJ file
+        return this._parseSolid(meshesNames, scene, data, rootUrl).then((meshes) => {
+            return {
+                meshes,
+                particleSystems: [],
+                skeletons: [],
+                animationGroups: []
+            };
+        });
+    }
+
+    /**
+     * 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
+     * @param fileName Defines the name of the file to load
+     * @returns a promise which completes when objects have been loaded to the scene
+     */
+    public loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<void> {
+        //Get the 3D model
+        return this.importMeshAsync(null, scene, data, rootUrl, onProgress).then(() => {
+            // return void
+        });
+    }
+
+    /**
+     * Load into an asset container.
+     * @param scene The scene to load into
+     * @param data The data to import
+     * @param rootUrl The root url for scene and resources
+     * @param onProgress The callback when the load progresses
+     * @param fileName Defines the name of the file to load
+     * @returns The loaded asset container
+     */
+    public loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<AssetContainer> {
+        return this.importMeshAsync(null, scene, data, rootUrl).then((result) => {
+            var container = new AssetContainer(scene);
+            result.meshes.forEach((mesh) => container.meshes.push(mesh));
+            container.removeAllFromScene();
+            return container;
+        });
+    }
+
+    /**
+     * Read the OBJ file and create an Array of meshes.
+     * Each mesh contains all information given by the OBJ and the MTL file.
+     * i.e. vertices positions and indices, optional normals values, optional UV values, optional material
+     *
+     * @param meshesNames
+     * @param scene Scene The scene where are displayed the data
+     * @param data String The content of the obj file
+     * @param rootUrl String The path to the folder
+     * @returns Array<AbstractMesh>
+     * @private
+     */
+    private _parseSolid(meshesNames: any, scene: Scene, data: string, rootUrl: string): Promise<Array<AbstractMesh>> {
+
+        var positions: Array<Vector3> = [];      //values for the positions of vertices
+        var normals: Array<Vector3> = [];      //Values for the normals
+        var uvs: Array<Vector2> = [];      //Values for the textures
+        var meshesFromObj: Array<any> = [];      //[mesh] Contains all the obj meshes
+        var handledMesh: any;      //The current mesh of meshes array
+        var indicesForBabylon: Array<number> = [];      //The list of indices for VertexData
+        var wrappedPositionForBabylon: Array<Vector3> = [];      //The list of position in vectors
+        var wrappedUvsForBabylon: Array<Vector2> = [];      //Array with all value of uvs to match with the indices
+        var wrappedNormalsForBabylon: Array<Vector3> = [];      //Array with all value of normals to match with the indices
+        var tuplePosNorm: Array<{ normals: Array<number>; idx: Array<number>; uv: Array<number> }> = [];      //Create a tuple with indice of Position, Normal, UV  [pos, norm, uvs]
+        var curPositionInIndices = 0;
+        var hasMeshes: Boolean = false;   //Meshes are defined in the file
+        var unwrappedPositionsForBabylon: Array<number> = [];      //Value of positionForBabylon w/o Vector3() [x,y,z]
+        var unwrappedNormalsForBabylon: Array<number> = [];      //Value of normalsForBabylon w/o Vector3()  [x,y,z]
+        var unwrappedUVForBabylon: Array<number> = [];      //Value of uvsForBabylon w/o Vector3()      [x,y,z]
+        var triangles: Array<string> = [];      //Indices from new triangles coming from polygons
+        var materialNameFromObj: string = "";      //The name of the current material
+        var fileToLoad: string = "";      //The name of the mtlFile to load
+        var materialsFromMTLFile: MTLFileLoader = new MTLFileLoader();
+        var objMeshName: string = "";      //The name of the current obj mesh
+        var increment: number = 1;      //Id for meshes created by the multimaterial
+        var isFirstMaterial: boolean = true;
+
+        /**
+         * Search for obj in the given array.
+         * This function is called to check if a couple of data already exists in an array.
+         *
+         * If found, returns the index of the founded tuple index. Returns -1 if not found
+         * @param arr Array<{ normals: Array<number>, idx: Array<number> }>
+         * @param obj Array<number>
+         * @returns {boolean}
+         */
+        var isInArray = (arr: Array<{ normals: Array<number>; idx: Array<number> }>, obj: Array<number>) => {
+            if (!arr[obj[0]]) { arr[obj[0]] = { normals: [], idx: [] }; }
+            var idx = arr[obj[0]].normals.indexOf(obj[1]);
+
+            return idx === -1 ? -1 : arr[obj[0]].idx[idx];
+        };
+        var isInArrayUV = (arr: Array<{ normals: Array<number>; idx: Array<number>; uv: Array<number> }>, obj: Array<number>) => {
+            if (!arr[obj[0]]) { arr[obj[0]] = { normals: [], idx: [], uv: [] }; }
+            var idx = arr[obj[0]].normals.indexOf(obj[1]);
+
+            if (idx != 1 && (obj[2] == arr[obj[0]].uv[idx])) {
+                return arr[obj[0]].idx[idx];
+            }
+            return -1;
+        };
+
+        /**
+         * This function set the data for each triangle.
+         * Data are position, normals and uvs
+         * If a tuple of (position, normal) is not set, add the data into the corresponding array
+         * If the tuple already exist, add only their indice
+         *
+         * @param indicePositionFromObj Integer The index in positions array
+         * @param indiceUvsFromObj Integer The index in uvs array
+         * @param indiceNormalFromObj Integer The index in normals array
+         * @param positionVectorFromOBJ Vector3 The value of position at index objIndice
+         * @param textureVectorFromOBJ Vector3 The value of uvs
+         * @param normalsVectorFromOBJ Vector3 The value of normals at index objNormale
+         */
+        var setData = (indicePositionFromObj: number, indiceUvsFromObj: number, indiceNormalFromObj: number, positionVectorFromOBJ: Vector3, textureVectorFromOBJ: Vector2, normalsVectorFromOBJ: Vector3) => {
+            //Check if this tuple already exists in the list of tuples
+            var _index: number;
+            if (OBJFileLoader.OPTIMIZE_WITH_UV) {
+                _index = isInArrayUV(
+                    tuplePosNorm,
+                    [
+                        indicePositionFromObj,
+                        indiceNormalFromObj,
+                        indiceUvsFromObj
+                    ]
+                );
+            }
+            else {
+                _index = isInArray(
+                    tuplePosNorm,
+                    [
+                        indicePositionFromObj,
+                        indiceNormalFromObj
+                    ]
+                );
+            }
+
+            //If it not exists
+            if (_index == -1) {
+                //Add an new indice.
+                //The array of indices is only an array with his length equal to the number of triangles - 1.
+                //We add vertices data in this order
+                indicesForBabylon.push(wrappedPositionForBabylon.length);
+                //Push the position of vertice for Babylon
+                //Each element is a Vector3(x,y,z)
+                wrappedPositionForBabylon.push(positionVectorFromOBJ);
+                //Push the uvs for Babylon
+                //Each element is a Vector3(u,v)
+                wrappedUvsForBabylon.push(textureVectorFromOBJ);
+                //Push the normals for Babylon
+                //Each element is a Vector3(x,y,z)
+                wrappedNormalsForBabylon.push(normalsVectorFromOBJ);
+                //Add the tuple in the comparison list
+                tuplePosNorm[indicePositionFromObj].normals.push(indiceNormalFromObj);
+                tuplePosNorm[indicePositionFromObj].idx.push(curPositionInIndices++);
+                if (OBJFileLoader.OPTIMIZE_WITH_UV) { tuplePosNorm[indicePositionFromObj].uv.push(indiceUvsFromObj); }
+            } else {
+                //The tuple already exists
+                //Add the index of the already existing tuple
+                //At this index we can get the value of position, normal and uvs of vertex
+                indicesForBabylon.push(_index);
+            }
+        };
+
+        /**
+         * Transform Vector() object onto 3 digits in an array
+         */
+        var unwrapData = () => {
+            //Every array has the same length
+            for (var l = 0; l < wrappedPositionForBabylon.length; l++) {
+                //Push the x, y, z values of each element in the unwrapped array
+                unwrappedPositionsForBabylon.push(wrappedPositionForBabylon[l].x, wrappedPositionForBabylon[l].y, wrappedPositionForBabylon[l].z);
+                unwrappedNormalsForBabylon.push(wrappedNormalsForBabylon[l].x, wrappedNormalsForBabylon[l].y, wrappedNormalsForBabylon[l].z);
+                unwrappedUVForBabylon.push(wrappedUvsForBabylon[l].x, wrappedUvsForBabylon[l].y); //z is an optional value not supported by BABYLON
+            }
+            // Reset arrays for the next new meshes
+            wrappedPositionForBabylon = [];
+            wrappedNormalsForBabylon = [];
+            wrappedUvsForBabylon = [];
+            tuplePosNorm = [];
+            curPositionInIndices = 0;
+        };
+
+        /**
+         * Create triangles from polygons by recursion
+         * The best to understand how it works is to draw it in the same time you get the recursion.
+         * It is important to notice that a triangle is a polygon
+         * We get 5 patterns of face defined in OBJ File :
+         * facePattern1 = ["1","2","3","4","5","6"]
+         * facePattern2 = ["1/1","2/2","3/3","4/4","5/5","6/6"]
+         * facePattern3 = ["1/1/1","2/2/2","3/3/3","4/4/4","5/5/5","6/6/6"]
+         * facePattern4 = ["1//1","2//2","3//3","4//4","5//5","6//6"]
+         * facePattern5 = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-4/-4/-4","-5/-5/-5","-6/-6/-6"]
+         * Each pattern is divided by the same method
+         * @param face Array[String] The indices of elements
+         * @param v Integer The variable to increment
+         */
+        var getTriangles = (face: Array<string>, v: number) => {
+            //Work for each element of the array
+            if (v + 1 < face.length) {
+                //Add on the triangle variable the indexes to obtain triangles
+                triangles.push(face[0], face[v], face[v + 1]);
+                //Incrementation for recursion
+                v += 1;
+                //Recursion
+                getTriangles(face, v);
+            }
+
+            //Result obtained after 2 iterations:
+            //Pattern1 => triangle = ["1","2","3","1","3","4"];
+            //Pattern2 => triangle = ["1/1","2/2","3/3","1/1","3/3","4/4"];
+            //Pattern3 => triangle = ["1/1/1","2/2/2","3/3/3","1/1/1","3/3/3","4/4/4"];
+            //Pattern4 => triangle = ["1//1","2//2","3//3","1//1","3//3","4//4"];
+            //Pattern5 => triangle = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-1/-1/-1","-3/-3/-3","-4/-4/-4"];
+        };
+
+        /**
+         * Create triangles and push the data for each polygon for the pattern 1
+         * In this pattern we get vertice positions
+         * @param face
+         * @param v
+         */
+        var setDataForCurrentFaceWithPattern1 = (face: Array<string>, v: number) => {
+            //Get the indices of triangles for each polygon
+            getTriangles(face, v);
+            //For each element in the triangles array.
+            //This var could contains 1 to an infinity of triangles
+            for (var k = 0; k < triangles.length; k++) {
+                // Set position indice
+                var indicePositionFromObj = parseInt(triangles[k]) - 1;
+
+                setData(
+                    indicePositionFromObj,
+                    0, 0,                                           //In the pattern 1, normals and uvs are not defined
+                    positions[indicePositionFromObj],               //Get the vectors data
+                    Vector2.Zero(), Vector3.Up()    //Create default vectors
+                );
+            }
+            //Reset variable for the next line
+            triangles = [];
+        };
+
+        /**
+         * Create triangles and push the data for each polygon for the pattern 2
+         * In this pattern we get vertice positions and uvsu
+         * @param face
+         * @param v
+         */
+        var setDataForCurrentFaceWithPattern2 = (face: Array<string>, v: number) => {
+            //Get the indices of triangles for each polygon
+            getTriangles(face, v);
+            for (var k = 0; k < triangles.length; k++) {
+                //triangle[k] = "1/1"
+                //Split the data for getting position and uv
+                var point = triangles[k].split("/"); // ["1", "1"]
+                //Set position indice
+                var indicePositionFromObj = parseInt(point[0]) - 1;
+                //Set uv indice
+                var indiceUvsFromObj = parseInt(point[1]) - 1;
+
+                setData(
+                    indicePositionFromObj,
+                    indiceUvsFromObj,
+                    0,                                  //Default value for normals
+                    positions[indicePositionFromObj],   //Get the values for each element
+                    uvs[indiceUvsFromObj],
+                    Vector3.Up()                //Default value for normals
+                );
+            }
+
+            //Reset variable for the next line
+            triangles = [];
+        };
+
+        /**
+         * Create triangles and push the data for each polygon for the pattern 3
+         * In this pattern we get vertice positions, uvs and normals
+         * @param face
+         * @param v
+         */
+        var setDataForCurrentFaceWithPattern3 = (face: Array<string>, v: number) => {
+            //Get the indices of triangles for each polygon
+            getTriangles(face, v);
+
+            for (var k = 0; k < triangles.length; k++) {
+                //triangle[k] = "1/1/1"
+                //Split the data for getting position, uv, and normals
+                var point = triangles[k].split("/"); // ["1", "1", "1"]
+                // Set position indice
+                var indicePositionFromObj = parseInt(point[0]) - 1;
+                // Set uv indice
+                var indiceUvsFromObj = parseInt(point[1]) - 1;
+                // Set normal indice
+                var indiceNormalFromObj = parseInt(point[2]) - 1;
+
+                setData(
+                    indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj,
+                    positions[indicePositionFromObj], uvs[indiceUvsFromObj], normals[indiceNormalFromObj] //Set the vector for each component
+                );
+
+            }
+            //Reset variable for the next line
+            triangles = [];
+        };
+
+        /**
+         * Create triangles and push the data for each polygon for the pattern 4
+         * In this pattern we get vertice positions and normals
+         * @param face
+         * @param v
+         */
+        var setDataForCurrentFaceWithPattern4 = (face: Array<string>, v: number) => {
+            getTriangles(face, v);
+
+            for (var k = 0; k < triangles.length; k++) {
+                //triangle[k] = "1//1"
+                //Split the data for getting position and normals
+                var point = triangles[k].split("//"); // ["1", "1"]
+                // We check indices, and normals
+                var indicePositionFromObj = parseInt(point[0]) - 1;
+                var indiceNormalFromObj = parseInt(point[1]) - 1;
+
+                setData(
+                    indicePositionFromObj,
+                    1, //Default value for uv
+                    indiceNormalFromObj,
+                    positions[indicePositionFromObj], //Get each vector of data
+                    Vector2.Zero(),
+                    normals[indiceNormalFromObj]
+                );
+            }
+            //Reset variable for the next line
+            triangles = [];
+        };
+
+        /**
+         * Create triangles and push the data for each polygon for the pattern 3
+         * In this pattern we get vertice positions, uvs and normals
+         * @param face
+         * @param v
+         */
+        var setDataForCurrentFaceWithPattern5 = (face: Array<string>, v: number) => {
+            //Get the indices of triangles for each polygon
+            getTriangles(face, v);
+
+            for (var k = 0; k < triangles.length; k++) {
+                //triangle[k] = "-1/-1/-1"
+                //Split the data for getting position, uv, and normals
+                var point = triangles[k].split("/"); // ["-1", "-1", "-1"]
+                // Set position indice
+                var indicePositionFromObj =  positions.length + parseInt(point[0]);
+                // Set uv indice
+                var indiceUvsFromObj =  uvs.length + parseInt(point[1]);
+                // Set normal indice
+                var indiceNormalFromObj = normals.length + parseInt(point[2]);
+
+                setData(
+                    indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj,
+                    positions[indicePositionFromObj], uvs[indiceUvsFromObj], normals[indiceNormalFromObj] //Set the vector for each component
+                );
+
+            }
+            //Reset variable for the next line
+            triangles = [];
+        };
+
+        var addPreviousObjMesh = () => {
+
+            //Check if it is not the first mesh. Otherwise we don't have data.
+            if (meshesFromObj.length > 0) {
+                //Get the previous mesh for applying the data about the faces
+                //=> in obj file, faces definition append after the name of the mesh
+                handledMesh = meshesFromObj[meshesFromObj.length - 1];
+
+                //Set the data into Array for the mesh
+                unwrapData();
+
+                // Reverse tab. Otherwise face are displayed in the wrong sens
+                indicesForBabylon.reverse();
+                //Set the information for the mesh
+                //Slice the array to avoid rewriting because of the fact this is the same var which be rewrited
+                handledMesh.indices = indicesForBabylon.slice();
+                handledMesh.positions = unwrappedPositionsForBabylon.slice();
+                handledMesh.normals = unwrappedNormalsForBabylon.slice();
+                handledMesh.uvs = unwrappedUVForBabylon.slice();
+
+                //Reset the array for the next mesh
+                indicesForBabylon = [];
+                unwrappedPositionsForBabylon = [];
+                unwrappedNormalsForBabylon = [];
+                unwrappedUVForBabylon = [];
+            }
+        };
+        //Main function
+
+        //Split the file into lines
+        var lines = data.split('\n');
+        //Look at each line
+        for (var i = 0; i < lines.length; i++) {
+            var line = lines[i].trim();
+            var result;
+
+            //Comment or newLine
+            if (line.length === 0 || line.charAt(0) === '#') {
+                continue;
+
+                //Get information about one position possible for the vertices
+            } else if ((result = this.vertexPattern.exec(line)) !== null) {
+                //Create a Vector3 with the position x, y, z
+                //Value of result:
+                // ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
+                //Add the Vector in the list of positions
+                positions.push(new Vector3(
+                    parseFloat(result[1]),
+                    parseFloat(result[2]),
+                    parseFloat(result[3])
+                ));
+
+            } else if ((result = this.normalPattern.exec(line)) !== null) {
+                //Create a Vector3 with the normals x, y, z
+                //Value of result
+                // ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
+                //Add the Vector in the list of normals
+                normals.push(new Vector3(
+                    parseFloat(result[1]),
+                    parseFloat(result[2]),
+                    parseFloat(result[3])
+                ));
+
+            } else if ((result = this.uvPattern.exec(line)) !== null) {
+                //Create a Vector2 with the normals u, v
+                //Value of result
+                // ["vt 0.1 0.2 0.3", "0.1", "0.2"]
+                //Add the Vector in the list of uvs
+                uvs.push(new Vector2(
+                    parseFloat(result[1]),
+                    parseFloat(result[2])
+                ));
+
+                //Identify patterns of faces
+                //Face could be defined in different type of pattern
+            } else if ((result = this.facePattern3.exec(line)) !== null) {
+                //Value of result:
+                //["f 1/1/1 2/2/2 3/3/3", "1/1/1 2/2/2 3/3/3"...]
+
+                //Set the data for this face
+                setDataForCurrentFaceWithPattern3(
+                    result[1].trim().split(" "), // ["1/1/1", "2/2/2", "3/3/3"]
+                    1
+                );
+
+            } else if ((result = this.facePattern4.exec(line)) !== null) {
+                //Value of result:
+                //["f 1//1 2//2 3//3", "1//1 2//2 3//3"...]
+
+                //Set the data for this face
+                setDataForCurrentFaceWithPattern4(
+                    result[1].trim().split(" "), // ["1//1", "2//2", "3//3"]
+                    1
+                );
+
+            } else if ((result = this.facePattern5.exec(line)) !== null) {
+                //Value of result:
+                //["f -1/-1/-1 -2/-2/-2 -3/-3/-3", "-1/-1/-1 -2/-2/-2 -3/-3/-3"...]
+
+                //Set the data for this face
+                setDataForCurrentFaceWithPattern5(
+                    result[1].trim().split(" "), // ["-1/-1/-1", "-2/-2/-2", "-3/-3/-3"]
+                    1
+                );
+
+            } else if ((result = this.facePattern2.exec(line)) !== null) {
+                //Value of result:
+                //["f 1/1 2/2 3/3", "1/1 2/2 3/3"...]
+
+                //Set the data for this face
+                setDataForCurrentFaceWithPattern2(
+                    result[1].trim().split(" "), // ["1/1", "2/2", "3/3"]
+                    1
+                );
+
+            } else if ((result = this.facePattern1.exec(line)) !== null) {
+                //Value of result
+                //["f 1 2 3", "1 2 3"...]
+
+                //Set the data for this face
+                setDataForCurrentFaceWithPattern1(
+                    result[1].trim().split(" "), // ["1", "2", "3"]
+                    1
+                );
+
+                //Define a mesh or an object
+                //Each time this keyword is analysed, create a new Object with all data for creating a babylonMesh
+            } else if (this.group.test(line) || this.obj.test(line)) {
+                //Create a new mesh corresponding to the name of the group.
+                //Definition of the mesh
+                var objMesh: {
+                    name: string;
+                    indices?: Array<number>;
+                    positions?: Array<number>;
+                    normals?: Array<number>;
+                    uvs?: Array<number>;
+                    materialName: string;
+                } =
+                //Set the name of the current obj mesh
+                {
+                    name: line.substring(2).trim(),
+                    indices: undefined,
+                    positions: undefined,
+                    normals: undefined,
+                    uvs: undefined,
+                    materialName: ""
+                };
+                addPreviousObjMesh();
+
+                //Push the last mesh created with only the name
+                meshesFromObj.push(objMesh);
+
+                //Set this variable to indicate that now meshesFromObj has objects defined inside
+                hasMeshes = true;
+                isFirstMaterial = true;
+                increment = 1;
+                //Keyword for applying a material
+            } else if (this.usemtl.test(line)) {
+                //Get the name of the material
+                materialNameFromObj = line.substring(7).trim();
+
+                //If this new material is in the same mesh
+
+                if (!isFirstMaterial) {
+                    //Set the data for the previous mesh
+                    addPreviousObjMesh();
+                    //Create a new mesh
+                    var objMesh: {
+                        name: string;
+                        indices?: Array<number>;
+                        positions?: Array<number>;
+                        normals?: Array<number>;
+                        uvs?: Array<number>;
+                        materialName: string;
+                    } =
+                    //Set the name of the current obj mesh
+                    {
+                        name: objMeshName + "_mm" + increment.toString(),
+                        indices: undefined,
+                        positions: undefined,
+                        normals: undefined,
+                        uvs: undefined,
+                        materialName: materialNameFromObj
+                    };
+                    increment++;
+                    //If meshes are already defined
+                    meshesFromObj.push(objMesh);
+                }
+                //Set the material name if the previous line define a mesh
+
+                if (hasMeshes && isFirstMaterial) {
+                    //Set the material name to the previous mesh (1 material per mesh)
+                    meshesFromObj[meshesFromObj.length - 1].materialName = materialNameFromObj;
+                    isFirstMaterial = false;
+                }
+                //Keyword for loading the mtl file
+            } else if (this.mtllib.test(line)) {
+                //Get the name of mtl file
+                fileToLoad = line.substring(7).trim();
+
+                //Apply smoothing
+            } else if (this.smooth.test(line)) {
+                // smooth shading => apply smoothing
+                //Toda  y I don't know it work with babylon and with obj.
+                //With the obj file  an integer is set
+            } else {
+                //If there is another possibility
+                console.log("Unhandled expression at line : " + line);
+            }
+        }
+
+        //At the end of the file, add the last mesh into the meshesFromObj array
+        if (hasMeshes) {
+            //Set the data for the last mesh
+            handledMesh = meshesFromObj[meshesFromObj.length - 1];
+
+            //Reverse indices for displaying faces in the good sens
+            indicesForBabylon.reverse();
+            //Get the good array
+            unwrapData();
+            //Set array
+            handledMesh.indices = indicesForBabylon;
+            handledMesh.positions = unwrappedPositionsForBabylon;
+            handledMesh.normals = unwrappedNormalsForBabylon;
+            handledMesh.uvs = unwrappedUVForBabylon;
+        }
+
+        //If any o or g keyword found, create a mesj with a random id
+        if (!hasMeshes) {
+            // reverse tab of indices
+            indicesForBabylon.reverse();
+            //Get positions normals uvs
+            unwrapData();
+            //Set data for one mesh
+            meshesFromObj.push({
+                name: Geometry.RandomId(),
+                indices: indicesForBabylon,
+                positions: unwrappedPositionsForBabylon,
+                normals: unwrappedNormalsForBabylon,
+                uvs: unwrappedUVForBabylon,
+                materialName: materialNameFromObj
+            });
+        }
+
+        //Create a Mesh list
+        var babylonMeshesArray: Array<Mesh> = []; //The mesh for babylon
+        var materialToUse = new Array<string>();
+
+        //Set data for each mesh
+        for (var j = 0; j < meshesFromObj.length; j++) {
+
+            //check meshesNames (stlFileLoader)
+            if (meshesNames && meshesFromObj[j].name) {
+                if (meshesNames instanceof Array) {
+                    if (meshesNames.indexOf(meshesFromObj[j].name) == -1) {
+                        continue;
+                    }
+                }
+                else {
+                    if (meshesFromObj[j].name !== meshesNames) {
+                        continue;
+                    }
+                }
+            }
+
+            //Get the current mesh
+            //Set the data with VertexBuffer for each mesh
+            handledMesh = meshesFromObj[j];
+            //Create a Mesh with the name of the obj mesh
+            var babylonMesh = new Mesh(meshesFromObj[j].name, scene);
+            //Push the name of the material to an array
+            //This is indispensable for the importMesh function
+            materialToUse.push(meshesFromObj[j].materialName);
+
+            var vertexData: VertexData = new VertexData(); //The container for the values
+            //Set the data for the babylonMesh
+            vertexData.positions = handledMesh.positions;
+            vertexData.normals = handledMesh.normals;
+            vertexData.uvs = handledMesh.uvs;
+            vertexData.indices = handledMesh.indices;
+            //Set the data from the VertexBuffer to the current Mesh
+            vertexData.applyToMesh(babylonMesh);
+            if (OBJFileLoader.INVERT_Y) {
+                babylonMesh.scaling.y *= -1;
+            }
+
+            //Push the mesh into an array
+            babylonMeshesArray.push(babylonMesh);
+        }
+
+        let mtlPromises: Array<Promise<any>> = [];
+        //load the materials
+        //Check if we have a file to load
+        if (fileToLoad !== "") {
+            //Load the file synchronously
+            mtlPromises.push(new Promise((resolve, reject) => {
+                this._loadMTL(fileToLoad, rootUrl, function(dataLoaded) {
+                    try {
+                        //Create materials thanks MTLLoader function
+                        materialsFromMTLFile.parseMTL(scene, dataLoaded, rootUrl);
+                        //Look at each material loaded in the mtl file
+                        for (var n = 0; n < materialsFromMTLFile.materials.length; n++) {
+                            //Three variables to get all meshes with the same material
+                            var startIndex = 0;
+                            var _indices = [];
+                            var _index;
+
+                            //The material from MTL file is used in the meshes loaded
+                            //Push the indice in an array
+                            //Check if the material is not used for another mesh
+                            while ((_index = materialToUse.indexOf(materialsFromMTLFile.materials[n].name, startIndex)) > -1) {
+                                _indices.push(_index);
+                                startIndex = _index + 1;
+                            }
+                            //If the material is not used dispose it
+                            if (_index == -1 && _indices.length == 0) {
+                                //If the material is not needed, remove it
+                                materialsFromMTLFile.materials[n].dispose();
+                            } else {
+                                for (var o = 0; o < _indices.length; o++) {
+                                    //Apply the material to the Mesh for each mesh with the material
+                                    babylonMeshesArray[_indices[o]].material = materialsFromMTLFile.materials[n];
+                                }
+                            }
+                        }
+                        resolve();
+                    } catch (e) {
+                        reject(e);
+                    }
+
+                });
+            }));
+
+        }
+        //Return an array with all Mesh
+        return Promise.all(mtlPromises).then(() => {
+            return babylonMeshesArray;
+        });
+    }
+
+}
+
+if (SceneLoader) {
+    //Add this loader into the register plugin
+    SceneLoader.RegisterPlugin(new OBJFileLoader());
+}

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

@@ -2,7 +2,7 @@
 import { ISceneV2, INodeV2, ICameraV2, IMeshPrimitiveV2, IMaterialV2, ITextureInfoV2, IAnimationV2 } from "./glTFLoaderInterfaces";
 import { IGLTFLoaderExtension } from "../glTFFileLoader";
 
-export var tata = 0;
+export var toto = 0;
 
 /**
  * Interface for a glTF loader extension.

+ 1 - 1
loaders/src/glTF/2.0/glTFLoaderInterfaces.ts

@@ -1,7 +1,7 @@
 import { VertexBuffer, Buffer, AnimationGroup, Material, AbstractMesh, Mesh, Bone, Skeleton } from "babylonjs";
 import { AnimationSamplerInterpolation, ITexture, ITextureInfo, IGLTF, ISampler, IScene, ISkin, IMesh, IMeshPrimitive, INode, IAccessor, IAnimationChannel, IAnimationSampler, IAnimation, IBuffer, IBufferView, ICamera, IImage, IMaterialNormalTextureInfo, IMaterialOcclusionTextureInfo, IMaterialPbrMetallicRoughness, IMaterial } from "babylonjs-gltf2interface";
 
-export var toto = 0;
+export var toto1 = 0;
 
 /**
  * Loader interface with an index field.

+ 5 - 5
loaders/src/legacy.ts

@@ -1,7 +1,7 @@
-import * as MatLib from "./index";
+import * as Loaders from "./index";
 
 /**
- * Legacy support, defining window.BABYLON.GridMaterial... (global variable).
+ * Legacy support, defining window.BABYLON.OBJLoader... (global variable).
  *
  * This is the entry point for the UMD module.
  * The entry point for a future ESM package should be index.ts
@@ -9,9 +9,9 @@ import * as MatLib from "./index";
 var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : undefined);
 if (typeof globalObject !== "undefined") {
     (<any>globalObject).BABYLON = (<any>globalObject).BABYLON || {};
-    for (var mat in MatLib) {
-        if (MatLib.hasOwnProperty(mat)) {
-            (<any>globalObject).BABYLON[mat] = (<any>MatLib)[mat];
+    for (var loader in Loaders) {
+        if (Loaders.hasOwnProperty(loader)) {
+            (<any>globalObject).BABYLON[loader] = (<any>Loaders)[loader];
         }
     }
 }

+ 19 - 0
serializers/legacy/legacy-glTF2Serializer.ts

@@ -0,0 +1,19 @@
+import * as Exporters from "../src/glTF/glTFFileExporter";
+import * as Serializers from "../src/glTF/2.0";
+
+/**
+ * This is the entry point for the UMD module.
+ * The entry point for a future ESM package should be index.ts
+ */
+var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : undefined);
+if (typeof globalObject !== "undefined") {
+    for (var exporter in Exporters) {
+        (<any>globalObject).BABYLON[exporter] = (<any>Exporters)[exporter];
+    }
+    for (var serializer in Serializers) {
+        (<any>globalObject).BABYLON[serializer] = (<any>Serializers)[serializer];
+    }
+}
+
+export * from "../src/glTF/glTFFileExporter";
+export * from "../src/glTF/2.0";

+ 14 - 0
serializers/legacy/legacy-objSerializer.ts

@@ -0,0 +1,14 @@
+import * as Serializers from "../src/OBJ";
+
+/**
+ * This is the entry point for the UMD module.
+ * The entry point for a future ESM package should be index.ts
+ */
+var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : undefined);
+if (typeof globalObject !== "undefined") {
+    for (var serializer in Serializers) {
+        (<any>globalObject).BABYLON[serializer] = (<any>Serializers)[serializer];
+    }
+}
+
+export * from "../src/OBJ";

+ 0 - 151
serializers/src/OBJ/babylon.objSerializer.ts

@@ -1,151 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON {
-    export class OBJExport {
-        //Exports the geometry of a Mesh array in .OBJ file format (text)
-        public static OBJ(mesh: Mesh[], materials?: boolean, matlibname?: string, globalposition?: boolean): string {
-            const output: string[] = [];
-            let v = 1;
-            if (materials) {
-                if (!matlibname) {
-                    matlibname = 'mat';
-                }
-                output.push("mtllib " + matlibname + ".mtl");
-            }
-            for (let j = 0; j < mesh.length; j++) {
-                output.push("g object" + j);
-                output.push("o object_" + j);
-
-                //Uses the position of the item in the scene, to the file (this back to normal in the end)
-                let lastMatrix: Nullable<Matrix> = null;
-                if (globalposition) {
-                    var newMatrix = BABYLON.Matrix.Translation(mesh[j].position.x, mesh[j].position.y, mesh[j].position.z);
-                    lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
-                    mesh[j].bakeTransformIntoVertices(newMatrix);
-                }
-
-                //TODO: submeshes (groups)
-                //TODO: smoothing groups (s 1, s off);
-                if (materials) {
-                    let mat = mesh[j].material;
-
-                    if (mat) {
-                        output.push("usemtl " + mat.id);
-                    }
-                }
-                const g: Nullable<Geometry> = mesh[j].geometry;
-
-                if (!g) {
-                    Tools.Warn("No geometry is present on the mesh");
-                    continue;
-                }
-
-                const trunkVerts = g.getVerticesData('position');
-                const trunkNormals = g.getVerticesData('normal');
-                const trunkUV = g.getVerticesData('uv');
-                const trunkFaces = g.getIndices();
-                var curV = 0;
-
-                if (!trunkVerts || !trunkFaces) {
-                    Tools.Warn("There are no position vertices or indices on the mesh!");
-                    continue;
-                }
-
-                for (var i = 0; i < trunkVerts.length; i += 3) {
-                    output.push("v " + trunkVerts[i] + " " + trunkVerts[i + 1] + " " + trunkVerts[i + 2]);
-                    curV++;
-                }
-
-                if (trunkNormals != null) {
-                    for (i = 0; i < trunkNormals.length; i += 3) {
-                        output.push("vn " + trunkNormals[i] + " " + trunkNormals[i + 1] + " " + trunkNormals[i + 2]);
-                    }
-                }
-                if (trunkUV != null) {
-
-                    for (i = 0; i < trunkUV.length; i += 2) {
-                        output.push("vt " + trunkUV[i] + " " + trunkUV[i + 1]);
-                    }
-                }
-
-                for (i = 0; i < trunkFaces.length; i += 3) {
-                    const indices = [String(trunkFaces[i + 2] + v), String(trunkFaces[i + 1] + v), String(trunkFaces[i] + v)];
-                    const blanks: string[] = ["", "", ""];
-
-                    const facePositions = indices;
-                    const faceUVs = trunkUV != null ? indices : blanks;
-                    const faceNormals = trunkNormals != null ? indices : blanks;
-
-                    output.push(
-                        "f " + facePositions[0] + "/" + faceUVs[0] + "/" + faceNormals[0] +
-                        " " + facePositions[1] + "/" + faceUVs[1] + "/" + faceNormals[1] +
-                        " " + facePositions[2] + "/" + faceUVs[2] + "/" + faceNormals[2]
-                    );
-                }
-                //back de previous matrix, to not change the original mesh in the scene
-                if (globalposition && lastMatrix) {
-                    mesh[j].bakeTransformIntoVertices(lastMatrix);
-                }
-                v += curV;
-            }
-            const text: string = output.join("\n");
-            return (text);
-        }
-        //Exports the material(s) of a mesh in .MTL file format (text)
-        //TODO: Export the materials of mesh array
-        public static MTL(mesh: Mesh): string {
-            var output = [];
-            var m = <StandardMaterial>mesh.material;
-            output.push("newmtl mat1");
-            output.push("  Ns " + m.specularPower.toFixed(4));
-            output.push("  Ni 1.5000");
-            output.push("  d " + m.alpha.toFixed(4));
-            output.push("  Tr 0.0000");
-            output.push("  Tf 1.0000 1.0000 1.0000");
-            output.push("  illum 2");
-            output.push("  Ka " + m.ambientColor.r.toFixed(4) + " " + m.ambientColor.g.toFixed(4) + " " + m.ambientColor.b.toFixed(4));
-            output.push("  Kd " + m.diffuseColor.r.toFixed(4) + " " + m.diffuseColor.g.toFixed(4) + " " + m.diffuseColor.b.toFixed(4));
-            output.push("  Ks " + m.specularColor.r.toFixed(4) + " " + m.specularColor.g.toFixed(4) + " " + m.specularColor.b.toFixed(4));
-            output.push("  Ke " + m.emissiveColor.r.toFixed(4) + " " + m.emissiveColor.g.toFixed(4) + " " + m.emissiveColor.b.toFixed(4));
-
-            //TODO: uv scale, offset, wrap
-            //TODO: UV mirrored in Blender? second UV channel? lightMap? reflection textures?
-            var uvscale = "";
-
-            if (m.ambientTexture) {
-                output.push("  map_Ka " + uvscale + m.ambientTexture.name);
-            }
-
-            if (m.diffuseTexture) {
-                output.push("  map_Kd " + uvscale + m.diffuseTexture.name);
-                //TODO: alpha testing, opacity in diffuse texture alpha channel (diffuseTexture.hasAlpha -> map_d)
-            }
-
-            if (m.specularTexture) {
-                output.push("  map_Ks " + uvscale + m.specularTexture.name);
-                /* TODO: glossiness = specular highlight component is in alpha channel of specularTexture. (???)
-                if (m.useGlossinessFromSpecularMapAlpha)  {
-                    output.push("  map_Ns "+uvscale + m.specularTexture.name);
-                }
-                */
-            }
-
-            /* TODO: emissive texture not in .MAT format (???)
-            if (m.emissiveTexture) {
-                output.push("  map_d "+uvscale+m.emissiveTexture.name);
-            }
-            */
-
-            if (m.bumpTexture) {
-                output.push("  map_bump -imfchan z " + uvscale + m.bumpTexture.name);
-            }
-
-            if (m.opacityTexture) {
-                output.push("  map_d " + uvscale + m.opacityTexture.name);
-            }
-
-            var text = output.join("\n");
-            return (text);
-        }
-    }
-}

+ 1 - 0
serializers/src/OBJ/index.ts

@@ -0,0 +1 @@
+export * from "./objSerializer";

+ 149 - 0
serializers/src/OBJ/objSerializer.ts

@@ -0,0 +1,149 @@
+import { Mesh, Nullable, Matrix, Geometry, Tools, StandardMaterial } from "babylonjs";
+
+export class OBJExport {
+    //Exports the geometry of a Mesh array in .OBJ file format (text)
+    public static OBJ(mesh: Mesh[], materials?: boolean, matlibname?: string, globalposition?: boolean): string {
+        const output: string[] = [];
+        let v = 1;
+        if (materials) {
+            if (!matlibname) {
+                matlibname = 'mat';
+            }
+            output.push("mtllib " + matlibname + ".mtl");
+        }
+        for (let j = 0; j < mesh.length; j++) {
+            output.push("g object" + j);
+            output.push("o object_" + j);
+
+            //Uses the position of the item in the scene, to the file (this back to normal in the end)
+            let lastMatrix: Nullable<Matrix> = null;
+            if (globalposition) {
+                var newMatrix = BABYLON.Matrix.Translation(mesh[j].position.x, mesh[j].position.y, mesh[j].position.z);
+                lastMatrix = BABYLON.Matrix.Translation(-(mesh[j].position.x), -(mesh[j].position.y), -(mesh[j].position.z));
+                mesh[j].bakeTransformIntoVertices(newMatrix);
+            }
+
+            //TODO: submeshes (groups)
+            //TODO: smoothing groups (s 1, s off);
+            if (materials) {
+                let mat = mesh[j].material;
+
+                if (mat) {
+                    output.push("usemtl " + mat.id);
+                }
+            }
+            const g: Nullable<Geometry> = mesh[j].geometry;
+
+            if (!g) {
+                Tools.Warn("No geometry is present on the mesh");
+                continue;
+            }
+
+            const trunkVerts = g.getVerticesData('position');
+            const trunkNormals = g.getVerticesData('normal');
+            const trunkUV = g.getVerticesData('uv');
+            const trunkFaces = g.getIndices();
+            var curV = 0;
+
+            if (!trunkVerts || !trunkFaces) {
+                Tools.Warn("There are no position vertices or indices on the mesh!");
+                continue;
+            }
+
+            for (var i = 0; i < trunkVerts.length; i += 3) {
+                output.push("v " + trunkVerts[i] + " " + trunkVerts[i + 1] + " " + trunkVerts[i + 2]);
+                curV++;
+            }
+
+            if (trunkNormals != null) {
+                for (i = 0; i < trunkNormals.length; i += 3) {
+                    output.push("vn " + trunkNormals[i] + " " + trunkNormals[i + 1] + " " + trunkNormals[i + 2]);
+                }
+            }
+            if (trunkUV != null) {
+
+                for (i = 0; i < trunkUV.length; i += 2) {
+                    output.push("vt " + trunkUV[i] + " " + trunkUV[i + 1]);
+                }
+            }
+
+            for (i = 0; i < trunkFaces.length; i += 3) {
+                const indices = [String(trunkFaces[i + 2] + v), String(trunkFaces[i + 1] + v), String(trunkFaces[i] + v)];
+                const blanks: string[] = ["", "", ""];
+
+                const facePositions = indices;
+                const faceUVs = trunkUV != null ? indices : blanks;
+                const faceNormals = trunkNormals != null ? indices : blanks;
+
+                output.push(
+                    "f " + facePositions[0] + "/" + faceUVs[0] + "/" + faceNormals[0] +
+                    " " + facePositions[1] + "/" + faceUVs[1] + "/" + faceNormals[1] +
+                    " " + facePositions[2] + "/" + faceUVs[2] + "/" + faceNormals[2]
+                );
+            }
+            //back de previous matrix, to not change the original mesh in the scene
+            if (globalposition && lastMatrix) {
+                mesh[j].bakeTransformIntoVertices(lastMatrix);
+            }
+            v += curV;
+        }
+        const text: string = output.join("\n");
+        return (text);
+    }
+    //Exports the material(s) of a mesh in .MTL file format (text)
+    //TODO: Export the materials of mesh array
+    public static MTL(mesh: Mesh): string {
+        var output = [];
+        var m = <StandardMaterial>mesh.material;
+        output.push("newmtl mat1");
+        output.push("  Ns " + m.specularPower.toFixed(4));
+        output.push("  Ni 1.5000");
+        output.push("  d " + m.alpha.toFixed(4));
+        output.push("  Tr 0.0000");
+        output.push("  Tf 1.0000 1.0000 1.0000");
+        output.push("  illum 2");
+        output.push("  Ka " + m.ambientColor.r.toFixed(4) + " " + m.ambientColor.g.toFixed(4) + " " + m.ambientColor.b.toFixed(4));
+        output.push("  Kd " + m.diffuseColor.r.toFixed(4) + " " + m.diffuseColor.g.toFixed(4) + " " + m.diffuseColor.b.toFixed(4));
+        output.push("  Ks " + m.specularColor.r.toFixed(4) + " " + m.specularColor.g.toFixed(4) + " " + m.specularColor.b.toFixed(4));
+        output.push("  Ke " + m.emissiveColor.r.toFixed(4) + " " + m.emissiveColor.g.toFixed(4) + " " + m.emissiveColor.b.toFixed(4));
+
+        //TODO: uv scale, offset, wrap
+        //TODO: UV mirrored in Blender? second UV channel? lightMap? reflection textures?
+        var uvscale = "";
+
+        if (m.ambientTexture) {
+            output.push("  map_Ka " + uvscale + m.ambientTexture.name);
+        }
+
+        if (m.diffuseTexture) {
+            output.push("  map_Kd " + uvscale + m.diffuseTexture.name);
+            //TODO: alpha testing, opacity in diffuse texture alpha channel (diffuseTexture.hasAlpha -> map_d)
+        }
+
+        if (m.specularTexture) {
+            output.push("  map_Ks " + uvscale + m.specularTexture.name);
+            /* TODO: glossiness = specular highlight component is in alpha channel of specularTexture. (???)
+            if (m.useGlossinessFromSpecularMapAlpha)  {
+                output.push("  map_Ns "+uvscale + m.specularTexture.name);
+            }
+            */
+        }
+
+        /* TODO: emissive texture not in .MAT format (???)
+        if (m.emissiveTexture) {
+            output.push("  map_d "+uvscale+m.emissiveTexture.name);
+        }
+        */
+
+        if (m.bumpTexture) {
+            output.push("  map_bump -imfchan z " + uvscale + m.bumpTexture.name);
+        }
+
+        if (m.opacityTexture) {
+            output.push("  map_d " + uvscale + m.opacityTexture.name);
+        }
+
+        var text = output.join("\n");
+        return (text);
+    }
+}

+ 100 - 100
serializers/src/glTF/2.0/Extensions/KHR_texture_transform.ts

@@ -1,113 +1,113 @@
-/// <reference path="../../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+import { Effect, Texture, Nullable, Vector2, Scene, BaseTexture, ProceduralTexture, Tools } from "babylonjs";
+import { ImageMimeType } from "babylonjs-gltf2interface";
+import { IGLTFExporterExtensionV2 } from "../glTFExporterExtension";
+import { _Exporter } from "../glTFExporter";
+
+const NAME = "KHR_texture_transform";
+
+Effect.ShadersStore["textureTransformPixelShader"] = require("../shaders/textureTransform.fragment.fx");
 
 /**
+ * Interface for handling KHR texture transform
  * @hidden
  */
-module BABYLON.GLTF2.Exporter.Extensions {
-    const NAME = "KHR_texture_transform";
+interface IKHRTextureTransform {
+    offset?: number[];
+    rotation?: number;
+    scale?: number[];
+    texCoord?: number;
+}
 
-    /**
-     * Interface for handling KHR texture transform
-     * @hidden
-     */
-    interface IKHRTextureTransform {
-        offset?: number[];
-        rotation?: number;
-        scale?: number[];
-        texCoord?: number;
+/**
+ * @hidden
+ */
+export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
+    /** Name of this extension */
+    public readonly name = NAME;
+
+    /** Defines whether this extension is enabled */
+    public enabled = true;
+
+    /** Defines whether this extension is required */
+    public required = false;
+
+    /** Reference to the glTF exporter */
+    private _exporter: _Exporter;
+
+    constructor(exporter: _Exporter) {
+        this._exporter = exporter;
+    }
+
+    public dispose() {
+        delete this._exporter;
+    }
+
+    public preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>> {
+        return new Promise((resolve, reject) => {
+            const texture_transform_extension: IKHRTextureTransform = {};
+
+            if (babylonTexture.uOffset !== 0 || babylonTexture.vOffset !== 0) {
+                texture_transform_extension.offset = [babylonTexture.uOffset, babylonTexture.vOffset];
+            }
+
+            if (babylonTexture.uScale !== 1 || babylonTexture.vScale !== 1) {
+                texture_transform_extension.scale = [babylonTexture.uScale, babylonTexture.vScale];
+            }
+
+            if (babylonTexture.wAng !== 0) {
+                texture_transform_extension.rotation = babylonTexture.wAng;
+            }
+
+            if (!Object.keys(texture_transform_extension).length) {
+                resolve(babylonTexture);
+            }
+
+            const scale = texture_transform_extension.scale ? new Vector2(texture_transform_extension.scale[0], texture_transform_extension.scale[1]) : Vector2.One();
+            const rotation = texture_transform_extension.rotation != null ? texture_transform_extension.rotation : 0;
+            const offset = texture_transform_extension.offset ? new Vector2(texture_transform_extension.offset[0], texture_transform_extension.offset[1]) : Vector2.Zero();
+            const scene = babylonTexture.getScene();
+            if (!scene) {
+                reject(`${context}: "scene" is not defined for Babylon texture ${babylonTexture.name}!`);
+            }
+            else {
+                this.textureTransformTextureAsync(babylonTexture, offset, rotation, scale, scene).then((texture) => {
+                    resolve(texture as Texture);
+                });
+            }
+        });
     }
 
     /**
-     * @hidden
+     * Transform the babylon texture by the offset, rotation and scale parameters using a procedural texture
+     * @param babylonTexture
+     * @param offset
+     * @param rotation
+     * @param scale
+     * @param scene
      */
-    export class KHR_texture_transform implements IGLTFExporterExtension {
-        /** Name of this extension */
-        public readonly name = NAME;
-
-        /** Defines whether this extension is enabled */
-        public enabled = true;
-
-        /** Defines whether this extension is required */
-        public required = false;
-
-        /** Reference to the glTF exporter */
-        private _exporter: _Exporter;
-
-        constructor(exporter: _Exporter) {
-            this._exporter = exporter;
-        }
-
-        public dispose() {
-            delete this._exporter;
-        }
-
-        public preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>> {
-            return new Promise((resolve, reject) => {
-                const texture_transform_extension: IKHRTextureTransform = {};
-
-                if (babylonTexture.uOffset !== 0 || babylonTexture.vOffset !== 0) {
-                    texture_transform_extension.offset = [babylonTexture.uOffset, babylonTexture.vOffset];
-                }
-
-                if (babylonTexture.uScale !== 1 || babylonTexture.vScale !== 1) {
-                    texture_transform_extension.scale = [babylonTexture.uScale, babylonTexture.vScale];
-                }
-
-                if (babylonTexture.wAng !== 0) {
-                    texture_transform_extension.rotation = babylonTexture.wAng;
-                }
-
-                if (!Object.keys(texture_transform_extension).length) {
-                    resolve(babylonTexture);
-                }
-
-                const scale = texture_transform_extension.scale ? new Vector2(texture_transform_extension.scale[0], texture_transform_extension.scale[1]) : Vector2.One();
-                const rotation = texture_transform_extension.rotation != null ? texture_transform_extension.rotation : 0;
-                const offset = texture_transform_extension.offset ? new Vector2(texture_transform_extension.offset[0], texture_transform_extension.offset[1]) : Vector2.Zero();
-                const scene = babylonTexture.getScene();
-                if (!scene) {
-                    reject(`${context}: "scene" is not defined for Babylon texture ${babylonTexture.name}!`);
-                }
-                else {
-                    this.textureTransformTextureAsync(babylonTexture, offset, rotation, scale, scene).then((texture) => {
-                        resolve(texture as Texture);
-                    });
-                }
-            });
-        }
-
-        /**
-         * Transform the babylon texture by the offset, rotation and scale parameters using a procedural texture
-         * @param babylonTexture
-         * @param offset
-         * @param rotation
-         * @param scale
-         * @param scene
-         */
-        public textureTransformTextureAsync(babylonTexture: Texture, offset: Vector2, rotation: number, scale: Vector2, scene: Scene): Promise<BaseTexture> {
-            return new Promise((resolve, reject) => {
-                const proceduralTexture = new ProceduralTexture(`${babylonTexture.name}`, babylonTexture.getSize(), "textureTransform", scene);
-                if (!proceduralTexture) {
-                    Tools.Log(`Cannot create procedural texture for ${babylonTexture.name}!`);
-                    resolve(babylonTexture);
-                }
-
-                proceduralTexture.setTexture("textureSampler", babylonTexture);
-                proceduralTexture.setMatrix("textureTransformMat", babylonTexture.getTextureMatrix());
-
-                // isReady trigger creation of effect if it doesnt exist yet
-                if (proceduralTexture.isReady()) {
+    public textureTransformTextureAsync(babylonTexture: Texture, offset: Vector2, rotation: number, scale: Vector2, scene: Scene): Promise<BaseTexture> {
+        return new Promise((resolve, reject) => {
+            const proceduralTexture = new ProceduralTexture(`${babylonTexture.name}`, babylonTexture.getSize(), "textureTransform", scene);
+            if (!proceduralTexture) {
+                Tools.Log(`Cannot create procedural texture for ${babylonTexture.name}!`);
+                resolve(babylonTexture);
+            }
+
+            proceduralTexture.setTexture("textureSampler", babylonTexture);
+            proceduralTexture.setMatrix("textureTransformMat", babylonTexture.getTextureMatrix());
+
+            // isReady trigger creation of effect if it doesnt exist yet
+            if (proceduralTexture.isReady()) {
+                proceduralTexture.render();
+                resolve(proceduralTexture);
+            } else {
+                (proceduralTexture as any).getEffect().executeWhenCompiled(() => {
                     proceduralTexture.render();
                     resolve(proceduralTexture);
-                } else {
-                    (proceduralTexture as any).getEffect().executeWhenCompiled(() => {
-                        proceduralTexture.render();
-                        resolve(proceduralTexture);
-                    });
-                }
-            });
-        }
+                });
+            }
+        });
     }
+}
 
-    _Exporter.RegisterExtension(NAME, (exporter) => new KHR_texture_transform(exporter));
-}
+_Exporter.RegisterExtension(NAME, (exporter) => new KHR_texture_transform(exporter));

+ 1 - 0
serializers/src/glTF/2.0/Extensions/index.ts

@@ -0,0 +1 @@
+export * from "./KHR_texture_transform";

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

@@ -1,782 +0,0 @@
-/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
-
-module BABYLON.GLTF2.Exporter {
-    /**
-     * @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 {
-        /**
-         * @ignore
-         *
-         * Creates glTF channel animation from BabylonJS animation.
-         * @param babylonTransformNode - 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(babylonTransformNode: TransformNode, 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(babylonTransformNode, animation, animationChannelTargetPath, minMaxKeyFrames.min, minMaxKeyFrames.max, animation.framePerSecond, animationSampleRate, inputs, outputs, minMaxKeyFrames, convertToRightHandedSystem, useQuaternion);
-            }
-            else {
-                if (interpolation === AnimationSamplerInterpolation.LINEAR || interpolation === AnimationSamplerInterpolation.STEP) {
-                    _GLTFAnimation._CreateLinearOrStepAnimation(babylonTransformNode, animation, animationChannelTargetPath, frameDelta, inputs, outputs, convertToRightHandedSystem, useQuaternion);
-
-                }
-                else if (interpolation === AnimationSamplerInterpolation.CUBICSPLINE) {
-                    _GLTFAnimation._CreateCubicSplineAnimation(babylonTransformNode, animation, animationChannelTargetPath, frameDelta, inputs, outputs, convertToRightHandedSystem, useQuaternion);
-                }
-                else {
-                    _GLTFAnimation._CreateBakedAnimation(babylonTransformNode, 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;
-        }
-
-        /**
-         * @ignore
-         * Create node animations from the transform node animations
-         * @param babylonTransformNode
-         * @param runtimeGLTFAnimation
-         * @param idleGLTFAnimations
-         * @param nodeMap
-         * @param nodes
-         * @param binaryWriter
-         * @param bufferViews
-         * @param accessors
-         * @param convertToRightHandedSystem
-         */
-        public static _CreateNodeAnimationFromTransformNodeAnimations(babylonTransformNode: TransformNode, runtimeGLTFAnimation: IAnimation, idleGLTFAnimations: IAnimation[], nodeMap: { [key: number]: number }, nodes: INode[], binaryWriter: _BinaryWriter, bufferViews: IBufferView[], accessors: IAccessor[], convertToRightHandedSystem: boolean, animationSampleRate: number) {
-            let glTFAnimation: IAnimation;
-            if (babylonTransformNode.animations) {
-                for (let animation of babylonTransformNode.animations) {
-                    let animationInfo = _GLTFAnimation._DeduceAnimationInfo(animation);
-                    if (animationInfo) {
-                        glTFAnimation = {
-                            name: animation.name,
-                            samplers: [],
-                            channels: []
-                        };
-                        _GLTFAnimation.AddAnimation(`${animation.name}`,
-                            animation.hasRunningRuntimeAnimations ? runtimeGLTFAnimation : glTFAnimation,
-                            babylonTransformNode,
-                            animation,
-                            animationInfo.dataAccessorType,
-                            animationInfo.animationChannelTargetPath,
-                            nodeMap,
-                            binaryWriter,
-                            bufferViews,
-                            accessors,
-                            convertToRightHandedSystem,
-                            animationInfo.useQuaternion,
-                            animationSampleRate
-                        );
-                        if (glTFAnimation.samplers.length && glTFAnimation.channels.length) {
-                            idleGLTFAnimations.push(glTFAnimation);
-                        }
-                    }
-                }
-            }
-        }
-
-        /**
-         * @ignore
-         * Create node animations from the animation groups
-         * @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;
-
-                for (let animationGroup of animationGroups) {
-                    glTFAnimation = {
-                        name: animationGroup.name,
-                        channels: [],
-                        samplers: []
-                    };
-                    for (let targetAnimation of animationGroup.targetedAnimations) {
-                        let target = targetAnimation.target;
-                        let animation = targetAnimation.animation;
-                        if (target instanceof Mesh || target.length === 1 && target[0] instanceof Mesh) { // TODO: Update to support bones
-                            let animationInfo = _GLTFAnimation._DeduceAnimationInfo(targetAnimation.animation);
-                            if (animationInfo) {
-                                let babylonMesh = target instanceof Mesh ? target : target[0] 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, babylonTransformNode: TransformNode, 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(babylonTransformNode, 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[babylonTransformNode.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 babylonTransformNode 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(babylonTransformNode: TransformNode, 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(babylonTransformNode, value, time, animation, animationChannelTargetPath, quaternionCache, inputs, outputs, convertToRightHandedSystem, useQuaternion);
-                    }
-                }
-            }
-            if (maxUsedFrame) {
-                minMaxFrames.max = maxUsedFrame;
-            }
-        }
-
-        private static _ConvertFactorToVector3OrQuaternion(factor: number, babylonTransformNode: TransformNode, 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(babylonTransformNode, 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': {
-                        value[componentName] = (convertToRightHandedSystem && useQuaternion && (animationChannelTargetPath !== AnimationChannelTargetPath.SCALE)) ? -factor : factor;
-                        break;
-                    }
-                    case 'y': {
-                        value[componentName] = (convertToRightHandedSystem && useQuaternion && (animationChannelTargetPath !== AnimationChannelTargetPath.SCALE)) ? -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(babylonTransformNode: TransformNode, 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, babylonTransformNode, 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) {
-                        _GLTFUtilities._GetRightHandedQuaternionFromRef(quaternionCache);
-
-                        if (!babylonTransformNode.parent) {
-                            quaternionCache = Quaternion.FromArray([0, 1, 0, 0]).multiply(quaternionCache);
-                        }
-                    }
-                    outputs.push(quaternionCache.asArray());
-                }
-                else {
-                    cacheValue = value as Vector3;
-                    if (convertToRightHandedSystem && (animationChannelTargetPath !== AnimationChannelTargetPath.SCALE)) {
-                        _GLTFUtilities._GetRightHandedPositionVector3FromRef(cacheValue);
-                        if (!babylonTransformNode.parent) {
-                            cacheValue.x *= -1;
-                            cacheValue.z *= -1;
-                        }
-                    }
-
-                    outputs.push(cacheValue.asArray());
-                }
-            }
-        }
-
-        /**
-         * Creates linear animation from the animation key frames
-         * @param babylonTransformNode 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(babylonTransformNode: TransformNode, animation: Animation, animationChannelTargetPath: AnimationChannelTargetPath, frameDelta: number, inputs: number[], outputs: number[][], convertToRightHandedSystem: boolean, useQuaternion: boolean) {
-            for (let keyFrame of animation.getKeys()) {
-                inputs.push(keyFrame.frame / animation.framePerSecond); // keyframes in seconds.
-                _GLTFAnimation._AddKeyframeValue(keyFrame, animation, outputs, animationChannelTargetPath, babylonTransformNode, convertToRightHandedSystem, useQuaternion);
-            }
-        }
-
-        /**
-         * Creates cubic spline animation from the animation key frames
-         * @param babylonTransformNode 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(babylonTransformNode: TransformNode, 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(
-                    babylonTransformNode,
-                    _TangentType.INTANGENT,
-                    outputs,
-                    animationChannelTargetPath,
-                    AnimationSamplerInterpolation.CUBICSPLINE,
-                    keyFrame,
-                    frameDelta,
-                    useQuaternion,
-                    convertToRightHandedSystem
-                );
-                _GLTFAnimation._AddKeyframeValue(keyFrame, animation, outputs, animationChannelTargetPath, babylonTransformNode, convertToRightHandedSystem, useQuaternion);
-
-                _GLTFAnimation.AddSplineTangent(
-                    babylonTransformNode,
-                    _TangentType.OUTTANGENT,
-                    outputs,
-                    animationChannelTargetPath,
-                    AnimationSamplerInterpolation.CUBICSPLINE,
-                    keyFrame,
-                    frameDelta,
-                    useQuaternion,
-                    convertToRightHandedSystem
-                );
-            });
-        }
-
-        private static _GetBasePositionRotationOrScale(babylonTransformNode: TransformNode, animationChannelTargetPath: AnimationChannelTargetPath, convertToRightHandedSystem: boolean, useQuaternion: boolean) {
-            let basePositionRotationOrScale: number[];
-            if (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
-                if (useQuaternion) {
-                    if (babylonTransformNode.rotationQuaternion) {
-                        basePositionRotationOrScale = babylonTransformNode.rotationQuaternion.asArray();
-                        if (convertToRightHandedSystem) {
-                            _GLTFUtilities._GetRightHandedQuaternionArrayFromRef(basePositionRotationOrScale);
-                            if (!babylonTransformNode.parent) {
-                                basePositionRotationOrScale = Quaternion.FromArray([0, 1, 0, 0]).multiply(Quaternion.FromArray(basePositionRotationOrScale)).asArray();
-                            }
-                        }
-                    }
-                    else {
-                        basePositionRotationOrScale = BABYLON.Quaternion.Identity().asArray();
-                    }
-                }
-                else {
-                    basePositionRotationOrScale = babylonTransformNode.rotation.asArray();
-                    _GLTFUtilities._GetRightHandedNormalArray3FromRef(basePositionRotationOrScale);
-                }
-            }
-            else if (animationChannelTargetPath === AnimationChannelTargetPath.TRANSLATION) {
-                basePositionRotationOrScale = babylonTransformNode.position.asArray();
-                if (convertToRightHandedSystem) {
-                    _GLTFUtilities._GetRightHandedPositionArray3FromRef(basePositionRotationOrScale);
-                }
-            }
-            else { // scale
-                basePositionRotationOrScale = babylonTransformNode.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, babylonTransformNode: TransformNode, 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 (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
-                    const array = Vector3.FromArray(value);
-                    let rotationQuaternion = Quaternion.RotationYawPitchRoll(array.y, array.x, array.z);
-                    if (convertToRightHandedSystem) {
-                        _GLTFUtilities._GetRightHandedQuaternionFromRef(rotationQuaternion);
-
-                        if (!babylonTransformNode.parent) {
-                            rotationQuaternion = Quaternion.FromArray([0, 1, 0, 0]).multiply(rotationQuaternion);
-                        }
-                    }
-                    value = rotationQuaternion.asArray();
-                }
-                else if (animationChannelTargetPath === AnimationChannelTargetPath.TRANSLATION) {
-                    if (convertToRightHandedSystem) {
-                        _GLTFUtilities._GetRightHandedNormalArray3FromRef(value);
-                        if (!babylonTransformNode.parent) {
-                            value[0] *= -1;
-                            value[2] *= -1;
-                        }
-                    }
-                }
-                outputs.push(value); // scale  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, babylonTransformNode, animation, animationType, animationChannelTargetPath, convertToRightHandedSystem, useQuaternion);
-                if (newPositionRotationOrScale) {
-                    if (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
-                        let posRotScale = useQuaternion ? newPositionRotationOrScale as Quaternion : Quaternion.RotationYawPitchRoll(newPositionRotationOrScale.y, newPositionRotationOrScale.x, newPositionRotationOrScale.z).normalize();
-                        if (convertToRightHandedSystem) {
-                            _GLTFUtilities._GetRightHandedQuaternionFromRef(posRotScale);
-
-                            if (!babylonTransformNode.parent) {
-                                posRotScale = Quaternion.FromArray([0, 1, 0, 0]).multiply(posRotScale);
-                            }
-                        }
-                        outputs.push(posRotScale.asArray());
-                    }
-                    else if (animationChannelTargetPath === AnimationChannelTargetPath.TRANSLATION) {
-                        if (convertToRightHandedSystem) {
-                            _GLTFUtilities._GetRightHandedNormalVector3FromRef(newPositionRotationOrScale as Vector3);
-
-                            if (!babylonTransformNode.parent) {
-                                newPositionRotationOrScale.x *= -1;
-                                newPositionRotationOrScale.z *= -1;
-                            }
-                        }
-                    }
-                    outputs.push(newPositionRotationOrScale.asArray());
-                }
-            }
-            else if (animationType === Animation.ANIMATIONTYPE_QUATERNION) {
-                value = (keyFrame.value as Quaternion).normalize().asArray();
-
-                if (convertToRightHandedSystem) {
-                    _GLTFUtilities._GetRightHandedQuaternionArrayFromRef(value);
-
-                    if (!babylonTransformNode.parent) {
-                        value = Quaternion.FromArray([0, 1, 0, 0]).multiply(Quaternion.FromArray(value)).asArray();
-                    }
-                }
-
-                outputs.push(value);
-            }
-            else {
-                Tools.Error('glTFAnimation: Unsupported key frame values for animation!');
-            }
-        }
-
-        /**
-         * Determine the interpolation based on the key frames
-         * @param keyFrames
-         * @param animationChannelTargetPath
-         * @param useQuaternion
-         */
-        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(babylonTransformNode: TransformNode, 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) {
-                        if (useQuaternion) {
-                            tangent = (tangentValue as Quaternion).scale(frameDelta).asArray();
-                        }
-                        else {
-                            const array = (tangentValue as Vector3).scale(frameDelta);
-                            tangent = Quaternion.RotationYawPitchRoll(array.y, array.x, array.z).asArray();
-                        }
-
-                        if (convertToRightHandedSystem) {
-                            _GLTFUtilities._GetRightHandedQuaternionArrayFromRef(tangent);
-                            if (!babylonTransformNode.parent) {
-                                tangent = Quaternion.FromArray([0, 1, 0, 0]).multiply(Quaternion.FromArray(tangent)).asArray();
-                            }
-                        }
-                    }
-                    else {
-                        tangent = [0, 0, 0, 0];
-                    }
-                }
-                else {
-                    if (tangentValue) {
-                        tangent = (tangentValue as Vector3).scale(frameDelta).asArray();
-                        if (convertToRightHandedSystem) {
-                            if (animationChannelTargetPath === AnimationChannelTargetPath.TRANSLATION) {
-                                _GLTFUtilities._GetRightHandedPositionArray3FromRef(tangent);
-                                if (!babylonTransformNode.parent) {
-                                    tangent[0] *= -1; // x
-                                    tangent[2] *= -1; // z
-                                }
-                            }
-                        }
-                    }
-                    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 };
-
-        }
-    }
-}

+ 0 - 64
serializers/src/glTF/2.0/babylon.glTFData.ts

@@ -1,64 +0,0 @@
-/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
-
-module BABYLON {
-    /**
-     * Class for holding and downloading glTF file data
-     */
-    export class GLTFData {
-        /**
-         * Object which contains the file name as the key and its data as the value
-         */
-        glTFFiles: { [fileName: string]: string | Blob };
-
-        /**
-         * Initializes the glTF file object
-         */
-        public constructor() {
-            this.glTFFiles = {};
-        }
-
-        /**
-         * Downloads the glTF data as files based on their names and data
-         */
-        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)
-            */
-            function endsWith(str: string, suffix: string): boolean {
-                return str.indexOf(suffix, str.length - suffix.length) !== -1;
-            }
-
-            for (let key in this.glTFFiles) {
-                let link = document.createElement('a');
-                document.body.appendChild(link);
-                link.setAttribute("type", "hidden");
-                link.download = key;
-                let blob = this.glTFFiles[key];
-                let mimeType;
-
-                if (endsWith(key, ".glb")) {
-                    mimeType = { type: "model/gltf-binary" };
-                }
-                else if (endsWith(key, ".bin")) {
-                    mimeType = { type: "application/octet-stream" };
-                }
-                else if (endsWith(key, ".gltf")) {
-                    mimeType = { type: "model/gltf+json" };
-                }
-                else if (endsWith(key, ".jpeg" || ".jpg")) {
-                    mimeType = {type: GLTF2.ImageMimeType.JPEG};
-                }
-                else if (endsWith(key, ".png")) {
-                    mimeType = {type: GLTF2.ImageMimeType.PNG};
-                }
-
-                link.href = window.URL.createObjectURL(new Blob([blob], mimeType));
-                link.click();
-            }
-
-        }
-    }
-}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 1562
serializers/src/glTF/2.0/babylon.glTFExporter.ts


+ 0 - 27
serializers/src/glTF/2.0/babylon.glTFExporterExtension.ts

@@ -1,27 +0,0 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
-
-module BABYLON.GLTF2.Exporter {
-    /**
-     * Interface for a glTF exporter extension
-     * @hidden
-     */
-    export interface IGLTFExporterExtension extends BABYLON.IGLTFExporterExtension, IDisposable {
-        /**
-         * Define this method to modify the default behavior before exporting a texture
-         * @param context The context when loading the asset
-         * @param babylonTexture The glTF texture info property
-         * @param mimeType The mime-type of the generated image
-         * @returns A promise that resolves with the exported glTF texture info when the export is complete, or null if not handled
-         */
-        preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
-
-        /**
-         * Define this method to modify the default behavior when exporting texture info
-         * @param context The context when loading the asset
-         * @param meshPrimitive glTF mesh primitive
-         * @param babylonSubMesh Babylon submesh
-         * @param binaryWriter glTF serializer binary writer instance
-         */
-        postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
-    }
-}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 1275
serializers/src/glTF/2.0/babylon.glTFMaterialExporter.ts


+ 0 - 84
serializers/src/glTF/2.0/babylon.glTFSerializer.ts

@@ -1,84 +0,0 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON {
-    /**
-     * Holds a collection of exporter options and parameters
-     */
-    export interface IExportOptions {
-        /**
-         * Function which indicates whether a babylon mesh should be exported or not
-         * @param transformNode source Babylon transform node. 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)
-         */
-        shouldExportTransformNode?(transformNode: TransformNode): boolean;
-        /**
-         * The sample rate to bake animation curves
-         */
-        animationSampleRate?: number;
-
-        /**
-         * Begin serialization without waiting for the scene to be ready
-         */
-        exportWithoutWaitingForScene?: boolean;
-    }
-
-    /**
-     * Class for generating glTF data from a Babylon scene.
-     */
-    export class GLTF2Export {
-        /**
-         * Exports the geometry of the scene to .gltf file format asynchronously
-         * @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 GLTFAsync(scene: Scene, filePrefix: string, options?: IExportOptions): Promise<GLTFData> {
-            return scene.whenReadyAsync().then(() => {
-                const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");
-                const gltfGenerator = new GLTF2.Exporter._Exporter(scene, options);
-                return gltfGenerator._generateGLTFAsync(glTFPrefix);
-            });
-        }
-
-        private static _PreExportAsync(scene: Scene, options?: IExportOptions): Promise<void> {
-            return Promise.resolve().then(() => {
-                if (options && options.exportWithoutWaitingForScene) {
-                    return Promise.resolve();
-                }
-                else {
-                    return scene.whenReadyAsync();
-                }
-            });
-        }
-
-        private static _PostExportAsync(scene: Scene, glTFData: GLTFData, options?: IExportOptions): Promise<GLTFData> {
-            return Promise.resolve().then(() => {
-                if (options && options.exportWithoutWaitingForScene) {
-                    return glTFData;
-                }
-                else {
-                    return glTFData;
-                }
-            });
-        }
-
-        /**
-         * Exports the geometry of the scene to .glb file format asychronously
-         * @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 GLBAsync(scene: Scene, filePrefix: string, options?: IExportOptions): Promise<GLTFData> {
-            return this._PreExportAsync(scene, options).then(() => {
-                const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");
-                const gltfGenerator = new GLTF2.Exporter._Exporter(scene, options);
-                return gltfGenerator._generateGLBAsync(glTFPrefix).then((glTFData) => {
-                    return this._PostExportAsync(scene, glTFData, options);
-                });
-            });
-        }
-    }
-}

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

@@ -1,195 +0,0 @@
-/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
-
-module BABYLON.GLTF2.Exporter {
-    /**
-     * @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 != null) {
-                accessor.min = min;
-            }
-            if (max != null) {
-                accessor.max = max;
-            }
-            if (byteOffset != null) {
-                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._GetRightHandedPositionVector3FromRef(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 _GetRightHandedPositionVector3(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 _GetRightHandedPositionVector3FromRef(vector: Vector3) {
-            vector.z *= -1;
-        }
-
-        /**
-         * Converts a three element number array to right-handed
-         * @param vector number array to convert to right-handed
-         */
-        public static _GetRightHandedPositionArray3FromRef(vector: number[]) {
-            vector[2] *= -1;
-        }
-
-        /**
-         * Converts a new right-handed Vector3
-         * @param vector vector3 array
-         * @returns right-handed Vector3
-         */
-        public static _GetRightHandedNormalVector3(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 _GetRightHandedNormalVector3FromRef(vector: Vector3) {
-            vector.z *= -1;
-        }
-
-        /**
-         * Converts a three element number array to right-handed
-         * @param vector number array to convert to right-handed
-         */
-        public static _GetRightHandedNormalArray3FromRef(vector: number[]) {
-            vector[2] *= -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 Vector4 to right-handed
-         * @param vector Vector4 to convert to right-handed
-         */
-        public static _GetRightHandedArray4FromRef(vector: number[]) {
-            vector[2] *= -1;
-            vector[3] *= -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;
-        }
-
-        /**
-         * Converts a Quaternion to right-handed
-         * @param quaternion Source quaternion to convert to right-handed
-         */
-        public static _GetRightHandedQuaternionArrayFromRef(quaternion: number[]) {
-            quaternion[0] *= -1;
-            quaternion[1] *= -1;
-        }
-
-        public static _NormalizeTangentFromRef(tangent: Vector4) {
-            const length = Math.sqrt(tangent.x * tangent.x + tangent.y * tangent.y + tangent.z * tangent.z);
-            if (length > 0) {
-                tangent.x /= length;
-                tangent.y /= length;
-                tangent.z /= length;
-            }
-        }
-    }
-}

+ 783 - 0
serializers/src/glTF/2.0/glTFAnimation.ts

@@ -0,0 +1,783 @@
+import { Animation, TransformNode, Nullable, Tools, Scene, Mesh, Vector3, Quaternion, IAnimationKey, AnimationKeyInterpolation } from "babylonjs";
+import { AnimationSamplerInterpolation, AnimationChannelTargetPath, AccessorType, IAnimation, INode, IBufferView, IAccessor, IAnimationSampler, IAnimationChannel, AccessorComponentType } from "babylonjs-gltf2interface";
+import { _BinaryWriter } from "./glTFExporter";
+import { _GLTFUtilities } from "./glTFUtilities";
+
+/**
+ * @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 {
+    /**
+     * @ignore
+     *
+     * Creates glTF channel animation from BabylonJS animation.
+     * @param babylonTransformNode - 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(babylonTransformNode: TransformNode, 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(babylonTransformNode, animation, animationChannelTargetPath, minMaxKeyFrames.min, minMaxKeyFrames.max, animation.framePerSecond, animationSampleRate, inputs, outputs, minMaxKeyFrames, convertToRightHandedSystem, useQuaternion);
+        }
+        else {
+            if (interpolation === AnimationSamplerInterpolation.LINEAR || interpolation === AnimationSamplerInterpolation.STEP) {
+                _GLTFAnimation._CreateLinearOrStepAnimation(babylonTransformNode, animation, animationChannelTargetPath, frameDelta, inputs, outputs, convertToRightHandedSystem, useQuaternion);
+
+            }
+            else if (interpolation === AnimationSamplerInterpolation.CUBICSPLINE) {
+                _GLTFAnimation._CreateCubicSplineAnimation(babylonTransformNode, animation, animationChannelTargetPath, frameDelta, inputs, outputs, convertToRightHandedSystem, useQuaternion);
+            }
+            else {
+                _GLTFAnimation._CreateBakedAnimation(babylonTransformNode, 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;
+    }
+
+    /**
+     * @ignore
+     * Create node animations from the transform node animations
+     * @param babylonTransformNode
+     * @param runtimeGLTFAnimation
+     * @param idleGLTFAnimations
+     * @param nodeMap
+     * @param nodes
+     * @param binaryWriter
+     * @param bufferViews
+     * @param accessors
+     * @param convertToRightHandedSystem
+     */
+    public static _CreateNodeAnimationFromTransformNodeAnimations(babylonTransformNode: TransformNode, runtimeGLTFAnimation: IAnimation, idleGLTFAnimations: IAnimation[], nodeMap: { [key: number]: number }, nodes: INode[], binaryWriter: _BinaryWriter, bufferViews: IBufferView[], accessors: IAccessor[], convertToRightHandedSystem: boolean, animationSampleRate: number) {
+        let glTFAnimation: IAnimation;
+        if (babylonTransformNode.animations) {
+            for (let animation of babylonTransformNode.animations) {
+                let animationInfo = _GLTFAnimation._DeduceAnimationInfo(animation);
+                if (animationInfo) {
+                    glTFAnimation = {
+                        name: animation.name,
+                        samplers: [],
+                        channels: []
+                    };
+                    _GLTFAnimation.AddAnimation(`${animation.name}`,
+                        animation.hasRunningRuntimeAnimations ? runtimeGLTFAnimation : glTFAnimation,
+                        babylonTransformNode,
+                        animation,
+                        animationInfo.dataAccessorType,
+                        animationInfo.animationChannelTargetPath,
+                        nodeMap,
+                        binaryWriter,
+                        bufferViews,
+                        accessors,
+                        convertToRightHandedSystem,
+                        animationInfo.useQuaternion,
+                        animationSampleRate
+                    );
+                    if (glTFAnimation.samplers.length && glTFAnimation.channels.length) {
+                        idleGLTFAnimations.push(glTFAnimation);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @ignore
+     * Create node animations from the animation groups
+     * @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;
+
+            for (let animationGroup of animationGroups) {
+                glTFAnimation = {
+                    name: animationGroup.name,
+                    channels: [],
+                    samplers: []
+                };
+                for (let targetAnimation of animationGroup.targetedAnimations) {
+                    let target = targetAnimation.target;
+                    let animation = targetAnimation.animation;
+                    if (target instanceof Mesh || target.length === 1 && target[0] instanceof Mesh) { // TODO: Update to support bones
+                        let animationInfo = _GLTFAnimation._DeduceAnimationInfo(targetAnimation.animation);
+                        if (animationInfo) {
+                            let babylonMesh = target instanceof Mesh ? target : target[0] 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, babylonTransformNode: TransformNode, 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(babylonTransformNode, 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[babylonTransformNode.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 babylonTransformNode 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(babylonTransformNode: TransformNode, 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(babylonTransformNode, value, time, animation, animationChannelTargetPath, quaternionCache, inputs, outputs, convertToRightHandedSystem, useQuaternion);
+                }
+            }
+        }
+        if (maxUsedFrame) {
+            minMaxFrames.max = maxUsedFrame;
+        }
+    }
+
+    private static _ConvertFactorToVector3OrQuaternion(factor: number, babylonTransformNode: TransformNode, 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(babylonTransformNode, 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': {
+                    value[componentName] = (convertToRightHandedSystem && useQuaternion && (animationChannelTargetPath !== AnimationChannelTargetPath.SCALE)) ? -factor : factor;
+                    break;
+                }
+                case 'y': {
+                    value[componentName] = (convertToRightHandedSystem && useQuaternion && (animationChannelTargetPath !== AnimationChannelTargetPath.SCALE)) ? -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(babylonTransformNode: TransformNode, 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, babylonTransformNode, 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) {
+                    _GLTFUtilities._GetRightHandedQuaternionFromRef(quaternionCache);
+
+                    if (!babylonTransformNode.parent) {
+                        quaternionCache = Quaternion.FromArray([0, 1, 0, 0]).multiply(quaternionCache);
+                    }
+                }
+                outputs.push(quaternionCache.asArray());
+            }
+            else {
+                cacheValue = value as Vector3;
+                if (convertToRightHandedSystem && (animationChannelTargetPath !== AnimationChannelTargetPath.SCALE)) {
+                    _GLTFUtilities._GetRightHandedPositionVector3FromRef(cacheValue);
+                    if (!babylonTransformNode.parent) {
+                        cacheValue.x *= -1;
+                        cacheValue.z *= -1;
+                    }
+                }
+
+                outputs.push(cacheValue.asArray());
+            }
+        }
+    }
+
+    /**
+     * Creates linear animation from the animation key frames
+     * @param babylonTransformNode 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(babylonTransformNode: TransformNode, animation: Animation, animationChannelTargetPath: AnimationChannelTargetPath, frameDelta: number, inputs: number[], outputs: number[][], convertToRightHandedSystem: boolean, useQuaternion: boolean) {
+        for (let keyFrame of animation.getKeys()) {
+            inputs.push(keyFrame.frame / animation.framePerSecond); // keyframes in seconds.
+            _GLTFAnimation._AddKeyframeValue(keyFrame, animation, outputs, animationChannelTargetPath, babylonTransformNode, convertToRightHandedSystem, useQuaternion);
+        }
+    }
+
+    /**
+     * Creates cubic spline animation from the animation key frames
+     * @param babylonTransformNode 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(babylonTransformNode: TransformNode, 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(
+                babylonTransformNode,
+                _TangentType.INTANGENT,
+                outputs,
+                animationChannelTargetPath,
+                AnimationSamplerInterpolation.CUBICSPLINE,
+                keyFrame,
+                frameDelta,
+                useQuaternion,
+                convertToRightHandedSystem
+            );
+            _GLTFAnimation._AddKeyframeValue(keyFrame, animation, outputs, animationChannelTargetPath, babylonTransformNode, convertToRightHandedSystem, useQuaternion);
+
+            _GLTFAnimation.AddSplineTangent(
+                babylonTransformNode,
+                _TangentType.OUTTANGENT,
+                outputs,
+                animationChannelTargetPath,
+                AnimationSamplerInterpolation.CUBICSPLINE,
+                keyFrame,
+                frameDelta,
+                useQuaternion,
+                convertToRightHandedSystem
+            );
+        });
+    }
+
+    private static _GetBasePositionRotationOrScale(babylonTransformNode: TransformNode, animationChannelTargetPath: AnimationChannelTargetPath, convertToRightHandedSystem: boolean, useQuaternion: boolean) {
+        let basePositionRotationOrScale: number[];
+        if (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
+            if (useQuaternion) {
+                if (babylonTransformNode.rotationQuaternion) {
+                    basePositionRotationOrScale = babylonTransformNode.rotationQuaternion.asArray();
+                    if (convertToRightHandedSystem) {
+                        _GLTFUtilities._GetRightHandedQuaternionArrayFromRef(basePositionRotationOrScale);
+                        if (!babylonTransformNode.parent) {
+                            basePositionRotationOrScale = Quaternion.FromArray([0, 1, 0, 0]).multiply(Quaternion.FromArray(basePositionRotationOrScale)).asArray();
+                        }
+                    }
+                }
+                else {
+                    basePositionRotationOrScale = BABYLON.Quaternion.Identity().asArray();
+                }
+            }
+            else {
+                basePositionRotationOrScale = babylonTransformNode.rotation.asArray();
+                _GLTFUtilities._GetRightHandedNormalArray3FromRef(basePositionRotationOrScale);
+            }
+        }
+        else if (animationChannelTargetPath === AnimationChannelTargetPath.TRANSLATION) {
+            basePositionRotationOrScale = babylonTransformNode.position.asArray();
+            if (convertToRightHandedSystem) {
+                _GLTFUtilities._GetRightHandedPositionArray3FromRef(basePositionRotationOrScale);
+            }
+        }
+        else { // scale
+            basePositionRotationOrScale = babylonTransformNode.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, babylonTransformNode: TransformNode, 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 (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
+                const array = Vector3.FromArray(value);
+                let rotationQuaternion = Quaternion.RotationYawPitchRoll(array.y, array.x, array.z);
+                if (convertToRightHandedSystem) {
+                    _GLTFUtilities._GetRightHandedQuaternionFromRef(rotationQuaternion);
+
+                    if (!babylonTransformNode.parent) {
+                        rotationQuaternion = Quaternion.FromArray([0, 1, 0, 0]).multiply(rotationQuaternion);
+                    }
+                }
+                value = rotationQuaternion.asArray();
+            }
+            else if (animationChannelTargetPath === AnimationChannelTargetPath.TRANSLATION) {
+                if (convertToRightHandedSystem) {
+                    _GLTFUtilities._GetRightHandedNormalArray3FromRef(value);
+                    if (!babylonTransformNode.parent) {
+                        value[0] *= -1;
+                        value[2] *= -1;
+                    }
+                }
+            }
+            outputs.push(value); // scale  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, babylonTransformNode, animation, animationType, animationChannelTargetPath, convertToRightHandedSystem, useQuaternion);
+            if (newPositionRotationOrScale) {
+                if (animationChannelTargetPath === AnimationChannelTargetPath.ROTATION) {
+                    let posRotScale = useQuaternion ? newPositionRotationOrScale as Quaternion : Quaternion.RotationYawPitchRoll(newPositionRotationOrScale.y, newPositionRotationOrScale.x, newPositionRotationOrScale.z).normalize();
+                    if (convertToRightHandedSystem) {
+                        _GLTFUtilities._GetRightHandedQuaternionFromRef(posRotScale);
+
+                        if (!babylonTransformNode.parent) {
+                            posRotScale = Quaternion.FromArray([0, 1, 0, 0]).multiply(posRotScale);
+                        }
+                    }
+                    outputs.push(posRotScale.asArray());
+                }
+                else if (animationChannelTargetPath === AnimationChannelTargetPath.TRANSLATION) {
+                    if (convertToRightHandedSystem) {
+                        _GLTFUtilities._GetRightHandedNormalVector3FromRef(newPositionRotationOrScale as Vector3);
+
+                        if (!babylonTransformNode.parent) {
+                            newPositionRotationOrScale.x *= -1;
+                            newPositionRotationOrScale.z *= -1;
+                        }
+                    }
+                }
+                outputs.push(newPositionRotationOrScale.asArray());
+            }
+        }
+        else if (animationType === Animation.ANIMATIONTYPE_QUATERNION) {
+            value = (keyFrame.value as Quaternion).normalize().asArray();
+
+            if (convertToRightHandedSystem) {
+                _GLTFUtilities._GetRightHandedQuaternionArrayFromRef(value);
+
+                if (!babylonTransformNode.parent) {
+                    value = Quaternion.FromArray([0, 1, 0, 0]).multiply(Quaternion.FromArray(value)).asArray();
+                }
+            }
+
+            outputs.push(value);
+        }
+        else {
+            Tools.Error('glTFAnimation: Unsupported key frame values for animation!');
+        }
+    }
+
+    /**
+     * Determine the interpolation based on the key frames
+     * @param keyFrames
+     * @param animationChannelTargetPath
+     * @param useQuaternion
+     */
+    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(babylonTransformNode: TransformNode, 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) {
+                    if (useQuaternion) {
+                        tangent = (tangentValue as Quaternion).scale(frameDelta).asArray();
+                    }
+                    else {
+                        const array = (tangentValue as Vector3).scale(frameDelta);
+                        tangent = Quaternion.RotationYawPitchRoll(array.y, array.x, array.z).asArray();
+                    }
+
+                    if (convertToRightHandedSystem) {
+                        _GLTFUtilities._GetRightHandedQuaternionArrayFromRef(tangent);
+                        if (!babylonTransformNode.parent) {
+                            tangent = Quaternion.FromArray([0, 1, 0, 0]).multiply(Quaternion.FromArray(tangent)).asArray();
+                        }
+                    }
+                }
+                else {
+                    tangent = [0, 0, 0, 0];
+                }
+            }
+            else {
+                if (tangentValue) {
+                    tangent = (tangentValue as Vector3).scale(frameDelta).asArray();
+                    if (convertToRightHandedSystem) {
+                        if (animationChannelTargetPath === AnimationChannelTargetPath.TRANSLATION) {
+                            _GLTFUtilities._GetRightHandedPositionArray3FromRef(tangent);
+                            if (!babylonTransformNode.parent) {
+                                tangent[0] *= -1; // x
+                                tangent[2] *= -1; // z
+                            }
+                        }
+                    }
+                }
+                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 };
+
+    }
+}

+ 61 - 0
serializers/src/glTF/2.0/glTFData.ts

@@ -0,0 +1,61 @@
+import { ImageMimeType } from "babylonjs-gltf2interface";
+
+/**
+ * Class for holding and downloading glTF file data
+ */
+export class GLTFData {
+    /**
+     * Object which contains the file name as the key and its data as the value
+     */
+    glTFFiles: { [fileName: string]: string | Blob };
+
+    /**
+     * Initializes the glTF file object
+     */
+    public constructor() {
+        this.glTFFiles = {};
+    }
+
+    /**
+     * Downloads the glTF data as files based on their names and data
+     */
+    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)
+        */
+        function endsWith(str: string, suffix: string): boolean {
+            return str.indexOf(suffix, str.length - suffix.length) !== -1;
+        }
+
+        for (let key in this.glTFFiles) {
+            let link = document.createElement('a');
+            document.body.appendChild(link);
+            link.setAttribute("type", "hidden");
+            link.download = key;
+            let blob = this.glTFFiles[key];
+            let mimeType;
+
+            if (endsWith(key, ".glb")) {
+                mimeType = { type: "model/gltf-binary" };
+            }
+            else if (endsWith(key, ".bin")) {
+                mimeType = { type: "application/octet-stream" };
+            }
+            else if (endsWith(key, ".gltf")) {
+                mimeType = { type: "model/gltf+json" };
+            }
+            else if (endsWith(key, ".jpeg" || ".jpg")) {
+                mimeType = {type: ImageMimeType.JPEG};
+            }
+            else if (endsWith(key, ".png")) {
+                mimeType = {type: ImageMimeType.PNG};
+            }
+
+            link.href = window.URL.createObjectURL(new Blob([blob], mimeType));
+            link.click();
+        }
+    }
+}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1564 - 0
serializers/src/glTF/2.0/glTFExporter.ts


+ 32 - 0
serializers/src/glTF/2.0/glTFExporterExtension.ts

@@ -0,0 +1,32 @@
+import { IDisposable, Texture, Nullable, SubMesh } from "babylonjs";
+
+import { ImageMimeType, IMeshPrimitive } from "babylonjs-gltf2interface";
+
+import { _BinaryWriter } from "./glTFExporter";
+import { IGLTFExporterExtension } from "../glTFFileExporter";
+
+export var toto2 = 0;
+
+/**
+ * Interface for a glTF exporter extension
+ * @hidden
+ */
+export interface IGLTFExporterExtensionV2 extends IGLTFExporterExtension, IDisposable {
+    /**
+     * Define this method to modify the default behavior before exporting a texture
+     * @param context The context when loading the asset
+     * @param babylonTexture The glTF texture info property
+     * @param mimeType The mime-type of the generated image
+     * @returns A promise that resolves with the exported glTF texture info when the export is complete, or null if not handled
+     */
+    preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
+
+    /**
+     * Define this method to modify the default behavior when exporting texture info
+     * @param context The context when loading the asset
+     * @param meshPrimitive glTF mesh primitive
+     * @param babylonSubMesh Babylon submesh
+     * @param binaryWriter glTF serializer binary writer instance
+     */
+    postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
+}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1275 - 0
serializers/src/glTF/2.0/glTFMaterialExporter.ts


+ 84 - 0
serializers/src/glTF/2.0/glTFSerializer.ts

@@ -0,0 +1,84 @@
+import { TransformNode, Scene } from "babylonjs";
+import { GLTFData } from "./glTFData";
+import { _Exporter } from "./glTFExporter";
+
+/**
+ * Holds a collection of exporter options and parameters
+ */
+export interface IExportOptions {
+    /**
+     * Function which indicates whether a babylon mesh should be exported or not
+     * @param transformNode source Babylon transform node. 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)
+     */
+    shouldExportTransformNode?(transformNode: TransformNode): boolean;
+    /**
+     * The sample rate to bake animation curves
+     */
+    animationSampleRate?: number;
+
+    /**
+     * Begin serialization without waiting for the scene to be ready
+     */
+    exportWithoutWaitingForScene?: boolean;
+}
+
+/**
+ * Class for generating glTF data from a Babylon scene.
+ */
+export class GLTF2Export {
+    /**
+     * Exports the geometry of the scene to .gltf file format asynchronously
+     * @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 GLTFAsync(scene: Scene, filePrefix: string, options?: IExportOptions): Promise<GLTFData> {
+        return scene.whenReadyAsync().then(() => {
+            const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");
+            const gltfGenerator = new _Exporter(scene, options);
+            return gltfGenerator._generateGLTFAsync(glTFPrefix);
+        });
+    }
+
+    private static _PreExportAsync(scene: Scene, options?: IExportOptions): Promise<void> {
+        return Promise.resolve().then(() => {
+            if (options && options.exportWithoutWaitingForScene) {
+                return Promise.resolve();
+            }
+            else {
+                return scene.whenReadyAsync();
+            }
+        });
+    }
+
+    private static _PostExportAsync(scene: Scene, glTFData: GLTFData, options?: IExportOptions): Promise<GLTFData> {
+        return Promise.resolve().then(() => {
+            if (options && options.exportWithoutWaitingForScene) {
+                return glTFData;
+            }
+            else {
+                return glTFData;
+            }
+        });
+    }
+
+    /**
+     * Exports the geometry of the scene to .glb file format asychronously
+     * @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 GLBAsync(scene: Scene, filePrefix: string, options?: IExportOptions): Promise<GLTFData> {
+        return this._PreExportAsync(scene, options).then(() => {
+            const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");
+            const gltfGenerator = new _Exporter(scene, options);
+            return gltfGenerator._generateGLBAsync(glTFPrefix).then((glTFData) => {
+                return this._PostExportAsync(scene, glTFData, options);
+            });
+        });
+    }
+}

+ 194 - 0
serializers/src/glTF/2.0/glTFUtilities.ts

@@ -0,0 +1,194 @@
+import { Nullable, FloatArray, Vector3, Vector4, Quaternion } from "babylonjs";
+import { IBufferView, AccessorType, AccessorComponentType, IAccessor } from "babylonjs-gltf2interface";
+
+/**
+ * @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 != null) {
+            accessor.min = min;
+        }
+        if (max != null) {
+            accessor.max = max;
+        }
+        if (byteOffset != null) {
+            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._GetRightHandedPositionVector3FromRef(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 _GetRightHandedPositionVector3(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 _GetRightHandedPositionVector3FromRef(vector: Vector3) {
+        vector.z *= -1;
+    }
+
+    /**
+     * Converts a three element number array to right-handed
+     * @param vector number array to convert to right-handed
+     */
+    public static _GetRightHandedPositionArray3FromRef(vector: number[]) {
+        vector[2] *= -1;
+    }
+
+    /**
+     * Converts a new right-handed Vector3
+     * @param vector vector3 array
+     * @returns right-handed Vector3
+     */
+    public static _GetRightHandedNormalVector3(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 _GetRightHandedNormalVector3FromRef(vector: Vector3) {
+        vector.z *= -1;
+    }
+
+    /**
+     * Converts a three element number array to right-handed
+     * @param vector number array to convert to right-handed
+     */
+    public static _GetRightHandedNormalArray3FromRef(vector: number[]) {
+        vector[2] *= -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 Vector4 to right-handed
+     * @param vector Vector4 to convert to right-handed
+     */
+    public static _GetRightHandedArray4FromRef(vector: number[]) {
+        vector[2] *= -1;
+        vector[3] *= -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;
+    }
+
+    /**
+     * Converts a Quaternion to right-handed
+     * @param quaternion Source quaternion to convert to right-handed
+     */
+    public static _GetRightHandedQuaternionArrayFromRef(quaternion: number[]) {
+        quaternion[0] *= -1;
+        quaternion[1] *= -1;
+    }
+
+    public static _NormalizeTangentFromRef(tangent: Vector4) {
+        const length = Math.sqrt(tangent.x * tangent.x + tangent.y * tangent.y + tangent.z * tangent.z);
+        if (length > 0) {
+            tangent.x /= length;
+            tangent.y /= length;
+            tangent.z /= length;
+        }
+    }
+}

+ 7 - 0
serializers/src/glTF/2.0/index.ts

@@ -0,0 +1,7 @@
+export * from "./glTFAnimation";
+export * from "./glTFData";
+export * from "./glTFExporter";
+export * from "./glTFExporterExtension";
+export * from "./glTFMaterialExporter";
+export * from "./glTFSerializer";
+export * from "./glTFUtilities";

+ 0 - 23
serializers/src/glTF/babylon.glTFFileExporter.ts

@@ -1,23 +0,0 @@
-/// <reference path="../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
-
-module BABYLON {
-    /**
-     * Interface for extending the exporter
-     * @hidden
-     */
-    export interface IGLTFExporterExtension {
-        /**
-         * The name of this extension
-         */
-        readonly name: string;
-        /**
-         * Defines whether this extension is enabled
-         */
-        enabled: boolean;
-
-        /**
-         * Defines whether this extension is required
-         */
-        required: boolean;
-    }
-}

+ 21 - 0
serializers/src/glTF/glTFFileExporter.ts

@@ -0,0 +1,21 @@
+export var toto3 = 0;
+
+/**
+ * Interface for extending the exporter
+ * @hidden
+ */
+export interface IGLTFExporterExtension {
+    /**
+     * The name of this extension
+     */
+    readonly name: string;
+    /**
+     * Defines whether this extension is enabled
+     */
+    enabled: boolean;
+
+    /**
+     * Defines whether this extension is required
+     */
+    required: boolean;
+}

+ 2 - 0
serializers/src/glTF/index.ts

@@ -0,0 +1,2 @@
+export * from "./glTFFileExporter";
+export * from "./2.0";

+ 2 - 0
serializers/src/index.ts

@@ -0,0 +1,2 @@
+export * from "./OBJ";
+export * from "./glTF";

+ 19 - 0
serializers/src/legacy.ts

@@ -0,0 +1,19 @@
+import * as Serializers from "./index";
+
+/**
+ * Legacy support, defining window.BABYLON.OBJSerializer... (global variable).
+ *
+ * This is the entry point for the UMD module.
+ * The entry point for a future ESM package should be index.ts
+ */
+var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : undefined);
+if (typeof globalObject !== "undefined") {
+    (<any>globalObject).BABYLON = (<any>globalObject).BABYLON || {};
+    for (var serializer in Serializers) {
+        if (Serializers.hasOwnProperty(serializer)) {
+            (<any>globalObject).BABYLON[serializer] = (<any>Serializers)[serializer];
+        }
+    }
+}
+
+export * from "./index";

+ 0 - 13
serializers/src/tsconfig.json

@@ -1,13 +0,0 @@
-{
-  "compilerOptions": {
-    "experimentalDecorators": true,
-    "module": "commonjs",
-    "target": "es5",
-    "lib": ["dom", "es2015.promise", "es5"],
-    "noImplicitAny": true,
-    "noImplicitReturns": true,
-    "noImplicitThis": true,
-    "noUnusedLocals": true,    
-    "strictNullChecks": true
-  }
-}

+ 41 - 0
serializers/tsconfig.json

@@ -0,0 +1,41 @@
+{
+  "compilerOptions": {
+      "experimentalDecorators": true,
+      "module": "commonjs",
+      "target": "es5",
+      "noImplicitAny": true,
+      "noImplicitReturns": true,
+      "noImplicitThis": true,
+      "noUnusedLocals": true,
+      "strictNullChecks": true,
+      "declaration": true,
+      "sourceMap": true,
+      "lib": [
+          "es5",
+          "dom",
+          "es2015.promise",
+          "es2015.collection",
+          "es2015.iterable"
+      ],
+      "skipDefaultLibCheck": true,
+      "skipLibCheck": true,
+      "baseUrl": "./src/",
+      "rootDir": "./",
+      "paths": {
+          "babylonjs": [
+            "../../dist/preview release/babylon.d.ts",
+          ],
+          "babylonjs-gltf2interface": [
+            "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"
+          ],
+      },
+      "outDir": "./build"
+  },
+  "include": [
+      "src/**/*"
+  ],
+  "exclude": [
+      "node_modules",
+      "**/*.spec.ts"
+  ]
+}

+ 74 - 0
serializers/webpack.config.js

@@ -0,0 +1,74 @@
+const path = require('path');
+const webpack = require('webpack');
+const DtsBundleWebpack = require('dts-bundle-webpack');
+const CleanWebpackPlugin = require('clean-webpack-plugin');
+
+module.exports = {
+    context: __dirname,
+    entry: {
+        'babylonjs-loaders': path.resolve(__dirname, './src/legacy.ts'),
+    },
+    output: {
+        path: path.resolve(__dirname, '../dist/preview release/serializers'),
+        filename: 'babylonjs.serializers.min.js',
+        libraryTarget: 'umd',
+        library: {
+            root: ["SERIALIZERS"],
+            amd: "babylonjs-serializers",
+            commonjs: "babylonjs-serializers"
+        },
+        umdNamedDefine: true
+    },
+    resolve: {
+        extensions: [".js", '.ts']
+    },
+    externals: {
+        babylonjs: {
+            root: "BABYLON",
+            commonjs: "babylonjs",
+            commonjs2: "babylonjs",
+            amd: "babylonjs"
+        }
+    },
+    devtool: "source-map",
+    module: {
+        rules: [{
+            test: /\.tsx?$/,
+            exclude: /node_modules/,
+            use: [
+            {
+                loader: 'awesome-typescript-loader',
+                options: {
+                    configFileName: '../../serializers/tsconfig.json',
+                    declarationDir: '../../dist/preview release/serializers/build'
+                }
+            }]
+        },
+        {
+            test: /\.fx$/,
+            use: [{
+                loader: path.resolve(__dirname, '../Tools/WebpackShaderLoader/index.js')
+            }]
+        }]
+    },
+    mode: "production",
+    devServer: {
+        contentBase: path.join(__dirname, "dist"),
+        compress: false,
+        //open: true,
+        port: 9000
+    },
+    plugins: [
+        new CleanWebpackPlugin([
+            path.resolve(__dirname, './src/**/*.js'),
+            path.resolve(__dirname, './src/**/*.map')
+        ]),
+        new webpack.WatchIgnorePlugin([
+            /\.js$/,
+            /\.d\.ts$/
+        ])
+    ],
+    watchOptions: {
+        ignored: [path.resolve(__dirname, './dist/**/*.*'), 'node_modules']
+    }
+}