Selaa lähdekoodia

Merge remote-tracking branch 'upstream/master'

sebastien 7 vuotta sitten
vanhempi
commit
052643459e
84 muutettua tiedostoa jossa 28657 lisäystä ja 18421 poistoa
  1. 7658 7314
      Playground/babylon.d.txt
  2. 1 0
      Playground/debug.html
  3. 1 0
      Playground/frame.html
  4. 1 0
      Playground/full.html
  5. 1 0
      Playground/index-local.html
  6. 1 0
      Playground/index.html
  7. 3 2
      Playground/indexStable.html
  8. 1 0
      Playground/zipContent/index.html
  9. 4 3
      Tools/Gulp/config.json
  10. 1 1
      Viewer/tests/validation/validate.html
  11. 2042 1869
      dist/preview release/babylon.d.ts
  12. 1 1
      dist/preview release/babylon.js
  13. 319 227
      dist/preview release/babylon.max.js
  14. 319 227
      dist/preview release/babylon.no-module.max.js
  15. 1 1
      dist/preview release/babylon.worker.js
  16. 319 227
      dist/preview release/es6.js
  17. 49 1
      dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts
  18. 8482 0
      dist/preview release/gltf_validator.js
  19. 1 1
      dist/preview release/gui/babylon.gui.js
  20. 1 1
      dist/preview release/gui/babylon.gui.min.js
  21. 1 1
      dist/preview release/gui/babylon.gui.min.js.map
  22. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js
  23. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js.map
  24. 5 2
      dist/preview release/inspector/babylon.inspector.d.ts
  25. 11 4
      dist/preview release/inspector/babylon.inspector.module.d.ts
  26. 38 25
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  27. 129 74
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  28. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  29. 74 61
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  30. 466 411
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  31. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  32. 74 61
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  33. 466 411
      dist/preview release/loaders/babylon.glTFFileLoader.js
  34. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  35. 6 6
      dist/preview release/loaders/babylon.objFileLoader.d.ts
  36. 6 6
      dist/preview release/loaders/babylon.objFileLoader.js
  37. 80 67
      dist/preview release/loaders/babylonjs.loaders.d.ts
  38. 472 417
      dist/preview release/loaders/babylonjs.loaders.js
  39. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  40. 80 67
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  41. 125 15
      dist/preview release/serializers/babylon.glTF2Serializer.d.ts
  42. 3086 2825
      dist/preview release/serializers/babylon.glTF2Serializer.js
  43. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  44. 125 15
      dist/preview release/serializers/babylonjs.serializers.d.ts
  45. 3086 2825
      dist/preview release/serializers/babylonjs.serializers.js
  46. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  47. 125 15
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  48. 35 728
      dist/preview release/typedocValidationBaseline.json
  49. 15 1
      dist/preview release/viewer/babylon.viewer.d.ts
  50. 1 1
      dist/preview release/viewer/babylon.viewer.js
  51. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  52. 18 1
      dist/preview release/viewer/babylon.viewer.module.d.ts
  53. 2 0
      dist/preview release/what's new.md
  54. 5 3
      gui/src/2D/controls/control.ts
  55. 9 0
      inspector/sass/tabs/_gltfTab.scss
  56. 2 2
      inspector/src/Inspector.ts
  57. 139 76
      inspector/src/tabs/GLTFTab.ts
  58. 17 4
      inspector/src/tabs/TabBar.ts
  59. 3 0
      inspector/tsconfig.json
  60. 6 0
      inspector/webpack.config.js
  61. 6 6
      loaders/src/OBJ/babylon.objFileLoader.ts
  62. 11 7
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  63. 0 1
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  64. 138 81
      loaders/src/glTF/babylon.glTFFileLoader.ts
  65. 1 0
      localDev/index.html
  66. 1 0
      sandbox/index-local.html
  67. 2 1
      sandbox/index.html
  68. 22 1
      sandbox/index.js
  69. 5 0
      src/Culling/babylon.boundingBox.ts
  70. 2 2
      src/Debug/babylon.debugLayer.ts
  71. 149 151
      src/Loading/babylon.sceneLoader.ts
  72. 11 8
      src/Mesh/babylon.mesh.ts
  73. 35 9
      src/Mesh/babylon.mesh.vertexData.ts
  74. 5 2
      src/Mesh/babylon.meshBuilder.ts
  75. 158 0
      src/Physics/babylon.IPhysicsEngine.ts
  76. 66 65
      src/Physics/babylon.physicsEngine.ts
  77. 98 0
      src/Physics/babylon.physicsEngineComponent.ts
  78. 1 1
      src/Physics/babylon.physicsHelper.ts
  79. 1 1
      src/Physics/babylon.physicsImpostor.ts
  80. 12 4
      src/Rendering/babylon.boundingBoxRenderer.ts
  81. 3 4
      src/Tools/babylon.filesInput.ts
  82. 3 65
      src/babylon.scene.ts
  83. 3 3
      src/babylon.sceneComponent.ts
  84. 1 0
      tests/validation/validate.html

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 7658 - 7314
Playground/babylon.d.txt


+ 1 - 0
Playground/debug.html

@@ -37,6 +37,7 @@
         <!-- Babylon.js -->
         <script src="https://preview.babylonjs.com/cannon.js"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
+        <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
         <script src="https://preview.babylonjs.com/babylon.max.js"></script>
         <script src="https://preview.babylonjs.com/gui/babylon.gui.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 1 - 0
Playground/frame.html

@@ -31,6 +31,7 @@
         <script src="https://preview.babylonjs.com/cannon.js"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
         <script src="https://preview.babylonjs.com/earcut.min.js"></script>
+        <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
         <script src="https://preview.babylonjs.com/babylon.js"></script>
         <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 1 - 0
Playground/full.html

@@ -28,6 +28,7 @@
         <!-- Babylon.js -->
         <script src="https://preview.babylonjs.com/cannon.js"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
+        <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
         <script src="https://preview.babylonjs.com/babylon.js"></script>
         <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 1 - 0
Playground/index-local.html

@@ -16,6 +16,7 @@
         <!-- Dependencies -->
         <script src="../dist/preview%20release/cannon.js"></script>
         <script src="../dist/preview%20release/Oimo.js"></script>
+        <script src="../dist/preview%20release/gltf_validator.js"></script>
         <script src="../dist/preview%20release/earcut.min.js"></script>
         <!-- Monaco -->
 

+ 1 - 0
Playground/index.html

@@ -36,6 +36,7 @@
         <!-- Dependencies -->
         <script src="https://preview.babylonjs.com/cannon.js"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
+        <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
         <script src="https://preview.babylonjs.com/earcut.min.js"></script>
         <!-- Babylon.js -->
         <script src="https://preview.babylonjs.com/babylon.js"></script>

+ 3 - 2
Playground/indexStable.html

@@ -35,8 +35,9 @@
         <script src="js/libs/fileSaver.js"></script>
         <!-- Physics -->
         <script src="https://cdn.babylonjs.com/cannon.js"></script>
-        <script src="https://cdn.babylonjs.com/Oimo.js"></script>        
-        <script src="https://preview.babylonjs.com/earcut.min.js"></script>
+        <script src="https://cdn.babylonjs.com/Oimo.js"></script>
+        <script src="https://cdn.babylonjs.com/gltf_validator.js"></script>
+        <script src="https://cdn.babylonjs.com/earcut.min.js"></script>
         <!-- Monaco -->
         <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
         <!-- Babylon.js -->

+ 1 - 0
Playground/zipContent/index.html

@@ -10,6 +10,7 @@
         <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
         <script src="https://preview.babylonjs.com/cannon.js"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
+        <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
         <script src="https://preview.babylonjs.com/earcut.min.js"></script>
         <script src="https://preview.babylonjs.com/babylon.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 4 - 3
Tools/Gulp/config.json

@@ -1087,7 +1087,8 @@
                 "../../src/Physics/babylon.physicsEngine.js",
                 "../../src/Physics/babylon.physicsHelper.js",
                 "../../src/Physics/Plugins/babylon.cannonJSPlugin.js",
-                "../../src/Physics/Plugins/babylon.oimoJSPlugin.js"
+                "../../src/Physics/Plugins/babylon.oimoJSPlugin.js",
+                "../../src/Physics/babylon.physicsEngineComponent.js"
             ],
             "dependUpon": [
                 "core",
@@ -1796,10 +1797,10 @@
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
-                    "../../loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts",
@@ -1822,10 +1823,10 @@
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
-                    "../../loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts",

+ 1 - 1
Viewer/tests/validation/validate.html

@@ -3,9 +3,9 @@
 <head>
 	<title>BabylonJS - Build validation page</title>
 	<link href="index.css" rel="stylesheet" />
-    <script src="https://preview.babylonjs.com/draco_decoder.js"></script>
     <script src="https://preview.babylonjs.com/cannon.js"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
+    <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
     <script src="https://preview.babylonjs.com/babylon.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2042 - 1869
dist/preview release/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/babylon.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 319 - 227
dist/preview release/babylon.max.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 319 - 227
dist/preview release/babylon.no-module.max.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/babylon.worker.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 319 - 227
dist/preview release/es6.js


+ 49 - 1
dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts

@@ -6,7 +6,7 @@ declare module "babylonjs-gltf2interface" {
     export = BABYLON.GLTF2;
 }
 /**
- * Moduel for glTF 2.0 Interface
+ * Module for glTF 2.0 Interface
  */
 declare module BABYLON.GLTF2 {
     /**
@@ -853,3 +853,51 @@ declare module BABYLON.GLTF2 {
         textures?: ITexture[];
     }
 }
+
+/**
+ * Interface for glTF validation results
+ */
+interface IGLTFValidationResults {
+    info: {
+        generator: string;
+        hasAnimations: boolean;
+        hasDefaultScene: boolean;
+        hasMaterials: boolean;
+        hasMorphTargets: boolean;
+        hasSkins: boolean;
+        hasTextures: boolean;
+        maxAttributesUsed: number;
+        primitivesCount: number
+    };
+    issues: {
+        messages: Array<string>;
+        numErrors: number;
+        numHints: number;
+        numInfos: number;
+        numWarnings: number;
+        truncated: boolean
+    };
+    mimeType: string;
+    uri: string;
+    validatedAt: string;
+    validatorVersion: string;
+}
+
+/**
+ * Interface for glTF validation options
+ */
+interface IGLTFValidationOptions {
+    uri?: string;
+    externalResourceFunction?: (uri: string) => Promise<Uint8Array>;
+    validateAccessorData?: boolean;
+    maxIssues?: number;
+    ignoredIssues?: Array<string>;
+    severityOverrides?: Object;
+}
+
+/**
+ * glTF validator object
+ */
+declare var GLTFValidator: {
+    validateString: (json: string, options?: IGLTFValidationOptions) => Promise<IGLTFValidationResults>;
+};

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 8482 - 0
dist/preview release/gltf_validator.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/gui/babylon.gui.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js.map


+ 5 - 2
dist/preview release/inspector/babylon.inspector.d.ts

@@ -33,7 +33,7 @@ declare module INSPECTOR {
                 * If the parameter 'popup' is false, the inspector is created as a right panel on the main window.
                 * If the parameter 'popup' is true, the inspector is created in another popup.
                 */
-            constructor(scene: BABYLON.Scene, popup?: boolean, initialTab?: number, parentElement?: BABYLON.Nullable<HTMLElement>, newColors?: {
+            constructor(scene: BABYLON.Scene, popup?: boolean, initialTab?: number | string, parentElement?: BABYLON.Nullable<HTMLElement>, newColors?: {
                     backgroundColor?: string;
                     backgroundColorLighter?: string;
                     backgroundColorLighter2?: string;
@@ -660,6 +660,8 @@ declare module INSPECTOR {
         static _Initialize(): void;
         constructor(tabbar: TabBar, inspector: Inspector);
         dispose(): void;
+        /** @hidden */
+        static _GetLoaderDefaultsAsync(): Promise<any>;
     }
 }
 declare module INSPECTOR {
@@ -778,7 +780,7 @@ declare module INSPECTOR {
         * The default active tab is the first one of the list.
         */
     export class TabBar extends BasicElement {
-            constructor(inspector: Inspector, initialTab?: number);
+            constructor(inspector: Inspector, initialTab?: number | string);
             update(): void;
             protected _build(): void;
             /** Dispose the current tab, set the given tab as active, and refresh the treeview */
@@ -790,6 +792,7 @@ declare module INSPECTOR {
             /** Returns the active tab */
             getActiveTab(): BABYLON.Nullable<Tab>;
             getActiveTabIndex(): number;
+            getTabIndex(name: string): number;
             readonly inspector: Inspector;
             /**
                 * Returns the total width in pixel of the tabbar,

+ 11 - 4
dist/preview release/inspector/babylon.inspector.module.d.ts

@@ -113,7 +113,7 @@ declare module 'babylonjs-inspector/Inspector' {
                 * If the parameter 'popup' is false, the inspector is created as a right panel on the main window.
                 * If the parameter 'popup' is true, the inspector is created in another popup.
                 */
-            constructor(scene: Scene, popup?: boolean, initialTab?: number, parentElement?: Nullable<HTMLElement>, newColors?: {
+            constructor(scene: Scene, popup?: boolean, initialTab?: number | string, parentElement?: Nullable<HTMLElement>, newColors?: {
                     backgroundColor?: string;
                     backgroundColorLighter?: string;
                     backgroundColorLighter2?: string;
@@ -835,12 +835,15 @@ declare module 'babylonjs-inspector/tabs/GLTFTab' {
     import { Inspector } from "babylonjs-inspector/Inspector";
     import { Tab } from "babylonjs-inspector/tabs/Tab";
     import { TabBar } from "babylonjs-inspector/tabs/TabBar";
+    import "babylonjs-gltf2interface";
     export class GLTFTab extends Tab {
         static readonly IsSupported: boolean;
         /** @hidden */
         static _Initialize(): void;
         constructor(tabbar: TabBar, inspector: Inspector);
         dispose(): void;
+        /** @hidden */
+        static _GetLoaderDefaultsAsync(): Promise<any>;
     }
 }
 
@@ -1014,7 +1017,7 @@ declare module 'babylonjs-inspector/tabs/TabBar' {
         * The default active tab is the first one of the list.
         */
     export class TabBar extends BasicElement {
-            constructor(inspector: Inspector, initialTab?: number);
+            constructor(inspector: Inspector, initialTab?: number | string);
             update(): void;
             protected _build(): void;
             /** Dispose the current tab, set the given tab as active, and refresh the treeview */
@@ -1026,6 +1029,7 @@ declare module 'babylonjs-inspector/tabs/TabBar' {
             /** Returns the active tab */
             getActiveTab(): Nullable<Tab>;
             getActiveTabIndex(): number;
+            getTabIndex(name: string): number;
             readonly inspector: Inspector;
             /**
                 * Returns the total width in pixel of the tabbar,
@@ -1373,7 +1377,7 @@ declare module INSPECTOR {
                 * If the parameter 'popup' is false, the inspector is created as a right panel on the main window.
                 * If the parameter 'popup' is true, the inspector is created in another popup.
                 */
-            constructor(scene: BABYLON.Scene, popup?: boolean, initialTab?: number, parentElement?: BABYLON.Nullable<HTMLElement>, newColors?: {
+            constructor(scene: BABYLON.Scene, popup?: boolean, initialTab?: number | string, parentElement?: BABYLON.Nullable<HTMLElement>, newColors?: {
                     backgroundColor?: string;
                     backgroundColorLighter?: string;
                     backgroundColorLighter2?: string;
@@ -2000,6 +2004,8 @@ declare module INSPECTOR {
         static _Initialize(): void;
         constructor(tabbar: TabBar, inspector: Inspector);
         dispose(): void;
+        /** @hidden */
+        static _GetLoaderDefaultsAsync(): Promise<any>;
     }
 }
 declare module INSPECTOR {
@@ -2118,7 +2124,7 @@ declare module INSPECTOR {
         * The default active tab is the first one of the list.
         */
     export class TabBar extends BasicElement {
-            constructor(inspector: Inspector, initialTab?: number);
+            constructor(inspector: Inspector, initialTab?: number | string);
             update(): void;
             protected _build(): void;
             /** Dispose the current tab, set the given tab as active, and refresh the treeview */
@@ -2130,6 +2136,7 @@ declare module INSPECTOR {
             /** Returns the active tab */
             getActiveTab(): BABYLON.Nullable<Tab>;
             getActiveTabIndex(): number;
+            getTabIndex(name: string): number;
             readonly inspector: Inspector;
             /**
                 * Returns the total width in pixel of the tabbar,

+ 38 - 25
dist/preview release/loaders/babylon.glTF1FileLoader.d.ts

@@ -1,4 +1,5 @@
 
+
 declare module BABYLON {
     /**
      * Mode that determines the coordinate system to use.
@@ -35,11 +36,11 @@ declare module BABYLON {
      */
     interface IGLTFLoaderData {
         /**
-         * JSON that represents the glTF.
+         * Object that represents the glTF JSON.
          */
         json: Object;
         /**
-         * The BIN chunk of a binary glTF
+         * The BIN chunk of a binary glTF.
          */
         bin: Nullable<ArrayBufferView>;
     }
@@ -76,13 +77,13 @@ declare module BABYLON {
     /** @hidden */
     interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
     /**
      * File loader for loading glTF files into a scene.
@@ -140,8 +141,6 @@ declare module BABYLON {
          * If true, no extra effects are applied to transparent pixels.
          */
         transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
         /**
          * Function called before loading a url referenced by the asset.
          */
@@ -224,15 +223,6 @@ declare module BABYLON {
          */
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         /**
-         * Returns a promise that resolves when the asset is completely loaded.
-         * @returns a promise that resolves when the asset is completely loaded.
-         */
-        whenCompleteAsync(): Promise<void>;
-        /**
-         * The loader state or null if the loader is not active.
-         */
-        readonly loaderState: Nullable<GLTFLoaderState>;
-        /**
          * Defines if the loader logging is enabled.
          */
         loggingEnabled: boolean;
@@ -240,6 +230,19 @@ declare module BABYLON {
          * Defines if the loader should capture performance counters.
          */
         capturePerformanceCounters: boolean;
+        /**
+         * Defines if the loader should validate the asset.
+         */
+        validate: boolean;
+        /**
+         * Observable raised after validation when validate is set to true. The event data is the result of the validation.
+         */
+        readonly onValidatedObservable: Observable<IGLTFValidationResults>;
+        private _onValidatedObserver;
+        /**
+         * Callback raised after a loader extension is created.
+         */
+        onValidated: (results: IGLTFValidationResults) => void;
         private _loader;
         /**
          * Name of the loader ("gltf")
@@ -262,10 +265,10 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -277,20 +280,20 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<AssetContainer>;
         /**
          * If the data string can be loaded directly.
          * @param data string contianing the file data
@@ -306,11 +309,21 @@ declare module BABYLON {
          * @returns the created plugin
          */
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
-        private _parse;
+        /**
+         * The loader state or null if the loader is not active.
+         */
+        readonly loaderState: Nullable<GLTFLoaderState>;
+        /**
+         * Returns a promise that resolves when the asset is completely loaded.
+         * @returns a promise that resolves when the asset is completely loaded.
+         */
+        whenCompleteAsync(): Promise<void>;
+        private _parseAsync;
+        private _validateAsync;
         private _getLoader;
-        private _parseBinary;
-        private _parseV1;
-        private _parseV2;
+        private _unpackBinary;
+        private _unpackBinaryV1;
+        private _unpackBinaryV2;
         private static _parseVersion;
         private static _compareVersion;
         private static _decodeBufferToText;

+ 129 - 74
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -1,4 +1,5 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
+/// <reference path="../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 var BABYLON;
 (function (BABYLON) {
     /**
@@ -56,13 +57,16 @@ var BABYLON;
      */
     var GLTFFileLoader = /** @class */ (function () {
         function GLTFFileLoader() {
-            // #region Common options
+            // --------------
+            // Common options
+            // --------------
             /**
              * Raised when the asset has been parsed
              */
             this.onParsedObservable = new BABYLON.Observable();
-            // #endregion
-            // #region V2 options
+            // ----------
+            // V2 options
+            // ----------
             /**
              * The coordinate system mode. Defaults to AUTO.
              */
@@ -89,8 +93,6 @@ var BABYLON;
              * If true, no extra effects are applied to transparent pixels.
              */
             this.transparencyAsCoverage = false;
-            /** @hidden */
-            this._normalizeAnimationGroupsToBeginAtZero = true;
             /**
              * Function called before loading a url referenced by the asset.
              */
@@ -130,7 +132,14 @@ var BABYLON;
              * Set additional options for a loader extension in this event.
              */
             this.onExtensionLoadedObservable = new BABYLON.Observable();
-            // #endregion
+            /**
+             * Defines if the loader should validate the asset.
+             */
+            this.validate = false;
+            /**
+             * Observable raised after validation when validate is set to true. The event data is the result of the validation.
+             */
+            this.onValidatedObservable = new BABYLON.Observable();
             this._loader = null;
             /**
              * Name of the loader ("gltf")
@@ -272,31 +281,6 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
-        /**
-         * Returns a promise that resolves when the asset is completely loaded.
-         * @returns a promise that resolves when the asset is completely loaded.
-         */
-        GLTFFileLoader.prototype.whenCompleteAsync = function () {
-            var _this = this;
-            return new Promise(function (resolve, reject) {
-                _this.onCompleteObservable.addOnce(function () {
-                    resolve();
-                });
-                _this.onErrorObservable.addOnce(function (reason) {
-                    reject(reason);
-                });
-            });
-        };
-        Object.defineProperty(GLTFFileLoader.prototype, "loaderState", {
-            /**
-             * The loader state or null if the loader is not active.
-             */
-            get: function () {
-                return this._loader ? this._loader.state : null;
-            },
-            enumerable: true,
-            configurable: true
-        });
         Object.defineProperty(GLTFFileLoader.prototype, "loggingEnabled", {
             /**
              * Defines if the loader logging is enabled.
@@ -343,6 +327,19 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(GLTFFileLoader.prototype, "onValidated", {
+            /**
+             * Callback raised after a loader extension is created.
+             */
+            set: function (callback) {
+                if (this._onValidatedObserver) {
+                    this.onValidatedObservable.remove(this._onValidatedObserver);
+                }
+                this._onValidatedObserver = this.onValidatedObservable.add(callback);
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Disposes the loader, releases resources during load, and cancels any outstanding requests.
          */
@@ -372,15 +369,15 @@ var BABYLON;
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
+        GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fileName) {
             var _this = this;
-            return Promise.resolve().then(function () {
-                var loaderData = _this._parse(data);
+            return this._parseAsync(scene, data, rootUrl, fileName).then(function (loaderData) {
+                _this._log("Loading " + (fileName || ""));
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress, fullName);
+                return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress, fileName);
             });
         };
         /**
@@ -389,15 +386,15 @@ var BABYLON;
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
+        GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fileName) {
             var _this = this;
-            return Promise.resolve().then(function () {
-                var loaderData = _this._parse(data);
+            return this._parseAsync(scene, data, rootUrl, fileName).then(function (loaderData) {
+                _this._log("Loading " + (fileName || ""));
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress, fullName);
+                return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress, fileName);
             });
         };
         /**
@@ -406,15 +403,15 @@ var BABYLON;
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
-         * @param fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fullName) {
+        GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fileName) {
             var _this = this;
-            return Promise.resolve().then(function () {
-                var loaderData = _this._parse(data);
+            return this._parseAsync(scene, data, rootUrl, fileName).then(function (loaderData) {
+                _this._log("Loading " + (fileName || ""));
                 _this._loader = _this._getLoader(loaderData);
-                return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress, fullName).then(function (result) {
+                return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress, fileName).then(function (result) {
                     var container = new BABYLON.AssetContainer(scene);
                     Array.prototype.push.apply(container.meshes, result.meshes);
                     Array.prototype.push.apply(container.particleSystems, result.particleSystems);
@@ -440,25 +437,70 @@ var BABYLON;
         GLTFFileLoader.prototype.createPlugin = function () {
             return new GLTFFileLoader();
         };
-        GLTFFileLoader.prototype._parse = function (data) {
-            this._startPerformanceCounter("Parse");
-            var parsedData;
-            if (data instanceof ArrayBuffer) {
-                this._log("Parsing binary");
-                parsedData = this._parseBinary(data);
+        Object.defineProperty(GLTFFileLoader.prototype, "loaderState", {
+            /**
+             * The loader state or null if the loader is not active.
+             */
+            get: function () {
+                return this._loader ? this._loader.state : null;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        /**
+         * Returns a promise that resolves when the asset is completely loaded.
+         * @returns a promise that resolves when the asset is completely loaded.
+         */
+        GLTFFileLoader.prototype.whenCompleteAsync = function () {
+            var _this = this;
+            return new Promise(function (resolve, reject) {
+                _this.onCompleteObservable.addOnce(function () {
+                    resolve();
+                });
+                _this.onErrorObservable.addOnce(function (reason) {
+                    reject(reason);
+                });
+            });
+        };
+        GLTFFileLoader.prototype._parseAsync = function (scene, data, rootUrl, fileName) {
+            var _this = this;
+            return Promise.resolve().then(function () {
+                var unpacked = (data instanceof ArrayBuffer) ? _this._unpackBinary(data) : { json: data, bin: null };
+                return _this._validateAsync(scene, unpacked.json, rootUrl, fileName).then(function () {
+                    _this._startPerformanceCounter("Parse JSON");
+                    _this._log("JSON length: " + unpacked.json.length);
+                    var loaderData = {
+                        json: JSON.parse(unpacked.json),
+                        bin: unpacked.bin
+                    };
+                    _this._endPerformanceCounter("Parse JSON");
+                    _this.onParsedObservable.notifyObservers(loaderData);
+                    _this.onParsedObservable.clear();
+                    return loaderData;
+                });
+            });
+        };
+        GLTFFileLoader.prototype._validateAsync = function (scene, json, rootUrl, fileName) {
+            var _this = this;
+            if (!this.validate || typeof GLTFValidator === "undefined") {
+                return Promise.resolve();
             }
-            else {
-                this._log("Parsing JSON");
-                this._log("JSON length: " + data.length);
-                parsedData = {
-                    json: JSON.parse(data),
-                    bin: null
-                };
+            this._startPerformanceCounter("Validate JSON");
+            var options = {
+                externalResourceFunction: function (uri) {
+                    return _this.preprocessUrlAsync(rootUrl + uri)
+                        .then(function (url) { return scene._loadFileAsync(url, true, true); })
+                        .then(function (data) { return new Uint8Array(data); });
+                }
+            };
+            if (fileName && fileName.substr(0, 5) !== "data:") {
+                options.uri = (rootUrl === "file:" ? fileName : "" + rootUrl + fileName);
             }
-            this.onParsedObservable.notifyObservers(parsedData);
-            this.onParsedObservable.clear();
-            this._endPerformanceCounter("Parse");
-            return parsedData;
+            return GLTFValidator.validateString(json, options).then(function (result) {
+                _this._endPerformanceCounter("Validate JSON");
+                _this.onValidatedObservable.notifyObservers(result);
+                _this.onValidatedObservable.clear();
+            });
         };
         GLTFFileLoader.prototype._getLoader = function (loaderData) {
             var asset = loaderData.json.asset || {};
@@ -488,11 +530,12 @@ var BABYLON;
             }
             return createLoader(this);
         };
-        GLTFFileLoader.prototype._parseBinary = function (data) {
+        GLTFFileLoader.prototype._unpackBinary = function (data) {
+            this._startPerformanceCounter("Unpack binary");
+            this._log("Binary length: " + data.byteLength);
             var Binary = {
                 Magic: 0x46546C67
             };
-            this._log("Binary length: " + data.byteLength);
             var binaryReader = new BinaryReader(data);
             var magic = binaryReader.readUint32();
             if (magic !== Binary.Magic) {
@@ -502,13 +545,24 @@ var BABYLON;
             if (this.loggingEnabled) {
                 this._log("Binary version: " + version);
             }
+            var unpacked;
             switch (version) {
-                case 1: return this._parseV1(binaryReader);
-                case 2: return this._parseV2(binaryReader);
+                case 1: {
+                    unpacked = this._unpackBinaryV1(binaryReader);
+                    break;
+                }
+                case 2: {
+                    unpacked = this._unpackBinaryV2(binaryReader);
+                    break;
+                }
+                default: {
+                    throw new Error("Unsupported version: " + version);
+                }
             }
-            throw new Error("Unsupported version: " + version);
+            this._endPerformanceCounter("Unpack binary");
+            return unpacked;
         };
-        GLTFFileLoader.prototype._parseV1 = function (binaryReader) {
+        GLTFFileLoader.prototype._unpackBinaryV1 = function (binaryReader) {
             var ContentFormat = {
                 JSON: 0
             };
@@ -521,7 +575,7 @@ var BABYLON;
             var content;
             switch (contentFormat) {
                 case ContentFormat.JSON: {
-                    content = JSON.parse(GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(contentLength)));
+                    content = GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(contentLength));
                     break;
                 }
                 default: {
@@ -535,7 +589,7 @@ var BABYLON;
                 bin: body
             };
         };
-        GLTFFileLoader.prototype._parseV2 = function (binaryReader) {
+        GLTFFileLoader.prototype._unpackBinaryV2 = function (binaryReader) {
             var ChunkFormat = {
                 JSON: 0x4E4F534A,
                 BIN: 0x004E4942
@@ -550,7 +604,7 @@ var BABYLON;
             if (chunkFormat !== ChunkFormat.JSON) {
                 throw new Error("First chunk format is not JSON");
             }
-            var json = JSON.parse(GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(chunkLength)));
+            var json = GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(chunkLength));
             // Look for BIN chunk
             var bin = null;
             while (binaryReader.getPosition() < binaryReader.getLength()) {
@@ -636,8 +690,9 @@ var BABYLON;
         };
         GLTFFileLoader.prototype._endPerformanceCounterDisabled = function (counterName) {
         };
-        // #endregion
-        // #region V1 options
+        // ----------
+        // V1 options
+        // ----------
         /**
          * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders.
          * Textures always loads asynchronously. For example, the success callback can compute the bounding information of the loaded meshes when incremental loading is disabled.

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 74 - 61
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -1,4 +1,5 @@
 
+
 declare module BABYLON {
     /**
      * Mode that determines the coordinate system to use.
@@ -35,11 +36,11 @@ declare module BABYLON {
      */
     interface IGLTFLoaderData {
         /**
-         * JSON that represents the glTF.
+         * Object that represents the glTF JSON.
          */
         json: Object;
         /**
-         * The BIN chunk of a binary glTF
+         * The BIN chunk of a binary glTF.
          */
         bin: Nullable<ArrayBufferView>;
     }
@@ -76,13 +77,13 @@ declare module BABYLON {
     /** @hidden */
     interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
     /**
      * File loader for loading glTF files into a scene.
@@ -140,8 +141,6 @@ declare module BABYLON {
          * If true, no extra effects are applied to transparent pixels.
          */
         transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
         /**
          * Function called before loading a url referenced by the asset.
          */
@@ -224,15 +223,6 @@ declare module BABYLON {
          */
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         /**
-         * Returns a promise that resolves when the asset is completely loaded.
-         * @returns a promise that resolves when the asset is completely loaded.
-         */
-        whenCompleteAsync(): Promise<void>;
-        /**
-         * The loader state or null if the loader is not active.
-         */
-        readonly loaderState: Nullable<GLTFLoaderState>;
-        /**
          * Defines if the loader logging is enabled.
          */
         loggingEnabled: boolean;
@@ -240,6 +230,19 @@ declare module BABYLON {
          * Defines if the loader should capture performance counters.
          */
         capturePerformanceCounters: boolean;
+        /**
+         * Defines if the loader should validate the asset.
+         */
+        validate: boolean;
+        /**
+         * Observable raised after validation when validate is set to true. The event data is the result of the validation.
+         */
+        readonly onValidatedObservable: Observable<IGLTFValidationResults>;
+        private _onValidatedObserver;
+        /**
+         * Callback raised after a loader extension is created.
+         */
+        onValidated: (results: IGLTFValidationResults) => void;
         private _loader;
         /**
          * Name of the loader ("gltf")
@@ -262,10 +265,10 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -277,20 +280,20 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<AssetContainer>;
         /**
          * If the data string can be loaded directly.
          * @param data string contianing the file data
@@ -306,11 +309,21 @@ declare module BABYLON {
          * @returns the created plugin
          */
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
-        private _parse;
+        /**
+         * The loader state or null if the loader is not active.
+         */
+        readonly loaderState: Nullable<GLTFLoaderState>;
+        /**
+         * Returns a promise that resolves when the asset is completely loaded.
+         * @returns a promise that resolves when the asset is completely loaded.
+         */
+        whenCompleteAsync(): Promise<void>;
+        private _parseAsync;
+        private _validateAsync;
         private _getLoader;
-        private _parseBinary;
-        private _parseV1;
-        private _parseV2;
+        private _unpackBinary;
+        private _unpackBinaryV1;
+        private _unpackBinaryV2;
         private static _parseVersion;
         private static _compareVersion;
         private static _decodeBufferToText;
@@ -338,7 +351,6 @@ declare module BABYLON {
 }
 
 
-
 declare module BABYLON.GLTF2 {
     /**
      * Loader interface with an index field.
@@ -571,7 +583,8 @@ declare module BABYLON.GLTF2 {
         private _state;
         private _extensions;
         private _rootUrl;
-        private _fullName;
+        private _fileName;
+        private _uniqueRootUrl;
         private _rootBabylonMesh;
         private _defaultBabylonMaterialData;
         private _progressCallback?;
@@ -600,14 +613,14 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
         /** @hidden */
-        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         private _loadAsync;
         private _loadData;
         private _setupData;
@@ -907,38 +920,6 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
-     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
-     */
-    class MSFT_audio_emitter implements IGLTFLoaderExtension {
-        /** The name of this extension. */
-        readonly name: string;
-        /** Defines whether this extension is enabled. */
-        enabled: boolean;
-        private _loader;
-        private _clips;
-        private _emitters;
-        /** @hidden */
-        constructor(loader: GLTFLoader);
-        /** @hidden */
-        dispose(): void;
-        /** @hidden */
-        onLoading(): void;
-        /** @hidden */
-        loadSceneAsync(context: string, scene: ILoaderScene): Nullable<Promise<void>>;
-        /** @hidden */
-        loadNodeAsync(context: string, node: ILoaderNode, assign: (babylonMesh: Mesh) => void): Nullable<Promise<Mesh>>;
-        /** @hidden */
-        loadAnimationAsync(context: string, animation: ILoaderAnimation): Nullable<Promise<AnimationGroup>>;
-        private _loadClipAsync;
-        private _loadEmitterAsync;
-        private _getEventAction;
-        private _loadAnimationEventAsync;
-    }
-}
-
-
-declare module BABYLON.GLTF2.Extensions {
-    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
      */
     class MSFT_lod implements IGLTFLoaderExtension {
@@ -1018,6 +999,38 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
+     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+     */
+    class MSFT_audio_emitter implements IGLTFLoaderExtension {
+        /** The name of this extension. */
+        readonly name: string;
+        /** Defines whether this extension is enabled. */
+        enabled: boolean;
+        private _loader;
+        private _clips;
+        private _emitters;
+        /** @hidden */
+        constructor(loader: GLTFLoader);
+        /** @hidden */
+        dispose(): void;
+        /** @hidden */
+        onLoading(): void;
+        /** @hidden */
+        loadSceneAsync(context: string, scene: ILoaderScene): Nullable<Promise<void>>;
+        /** @hidden */
+        loadNodeAsync(context: string, node: ILoaderNode, assign: (babylonMesh: Mesh) => void): Nullable<Promise<Mesh>>;
+        /** @hidden */
+        loadAnimationAsync(context: string, animation: ILoaderAnimation): Nullable<Promise<AnimationGroup>>;
+        private _loadClipAsync;
+        private _loadEmitterAsync;
+        private _getEventAction;
+        private _loadAnimationEventAsync;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
      */
     class KHR_draco_mesh_compression implements IGLTFLoaderExtension {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 466 - 411
dist/preview release/loaders/babylon.glTF2FileLoader.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 74 - 61
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -1,4 +1,5 @@
 
+
 declare module BABYLON {
     /**
      * Mode that determines the coordinate system to use.
@@ -35,11 +36,11 @@ declare module BABYLON {
      */
     interface IGLTFLoaderData {
         /**
-         * JSON that represents the glTF.
+         * Object that represents the glTF JSON.
          */
         json: Object;
         /**
-         * The BIN chunk of a binary glTF
+         * The BIN chunk of a binary glTF.
          */
         bin: Nullable<ArrayBufferView>;
     }
@@ -76,13 +77,13 @@ declare module BABYLON {
     /** @hidden */
     interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
     /**
      * File loader for loading glTF files into a scene.
@@ -140,8 +141,6 @@ declare module BABYLON {
          * If true, no extra effects are applied to transparent pixels.
          */
         transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
         /**
          * Function called before loading a url referenced by the asset.
          */
@@ -224,15 +223,6 @@ declare module BABYLON {
          */
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         /**
-         * Returns a promise that resolves when the asset is completely loaded.
-         * @returns a promise that resolves when the asset is completely loaded.
-         */
-        whenCompleteAsync(): Promise<void>;
-        /**
-         * The loader state or null if the loader is not active.
-         */
-        readonly loaderState: Nullable<GLTFLoaderState>;
-        /**
          * Defines if the loader logging is enabled.
          */
         loggingEnabled: boolean;
@@ -240,6 +230,19 @@ declare module BABYLON {
          * Defines if the loader should capture performance counters.
          */
         capturePerformanceCounters: boolean;
+        /**
+         * Defines if the loader should validate the asset.
+         */
+        validate: boolean;
+        /**
+         * Observable raised after validation when validate is set to true. The event data is the result of the validation.
+         */
+        readonly onValidatedObservable: Observable<IGLTFValidationResults>;
+        private _onValidatedObserver;
+        /**
+         * Callback raised after a loader extension is created.
+         */
+        onValidated: (results: IGLTFValidationResults) => void;
         private _loader;
         /**
          * Name of the loader ("gltf")
@@ -262,10 +265,10 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -277,20 +280,20 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<AssetContainer>;
         /**
          * If the data string can be loaded directly.
          * @param data string contianing the file data
@@ -306,11 +309,21 @@ declare module BABYLON {
          * @returns the created plugin
          */
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
-        private _parse;
+        /**
+         * The loader state or null if the loader is not active.
+         */
+        readonly loaderState: Nullable<GLTFLoaderState>;
+        /**
+         * Returns a promise that resolves when the asset is completely loaded.
+         * @returns a promise that resolves when the asset is completely loaded.
+         */
+        whenCompleteAsync(): Promise<void>;
+        private _parseAsync;
+        private _validateAsync;
         private _getLoader;
-        private _parseBinary;
-        private _parseV1;
-        private _parseV2;
+        private _unpackBinary;
+        private _unpackBinaryV1;
+        private _unpackBinaryV2;
         private static _parseVersion;
         private static _compareVersion;
         private static _decodeBufferToText;
@@ -900,7 +913,6 @@ declare module BABYLON.GLTF1 {
 }
 
 
-
 declare module BABYLON.GLTF2 {
     /**
      * Loader interface with an index field.
@@ -1133,7 +1145,8 @@ declare module BABYLON.GLTF2 {
         private _state;
         private _extensions;
         private _rootUrl;
-        private _fullName;
+        private _fileName;
+        private _uniqueRootUrl;
         private _rootBabylonMesh;
         private _defaultBabylonMaterialData;
         private _progressCallback?;
@@ -1162,14 +1175,14 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
         /** @hidden */
-        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         private _loadAsync;
         private _loadData;
         private _setupData;
@@ -1469,38 +1482,6 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
-     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
-     */
-    class MSFT_audio_emitter implements IGLTFLoaderExtension {
-        /** The name of this extension. */
-        readonly name: string;
-        /** Defines whether this extension is enabled. */
-        enabled: boolean;
-        private _loader;
-        private _clips;
-        private _emitters;
-        /** @hidden */
-        constructor(loader: GLTFLoader);
-        /** @hidden */
-        dispose(): void;
-        /** @hidden */
-        onLoading(): void;
-        /** @hidden */
-        loadSceneAsync(context: string, scene: ILoaderScene): Nullable<Promise<void>>;
-        /** @hidden */
-        loadNodeAsync(context: string, node: ILoaderNode, assign: (babylonMesh: Mesh) => void): Nullable<Promise<Mesh>>;
-        /** @hidden */
-        loadAnimationAsync(context: string, animation: ILoaderAnimation): Nullable<Promise<AnimationGroup>>;
-        private _loadClipAsync;
-        private _loadEmitterAsync;
-        private _getEventAction;
-        private _loadAnimationEventAsync;
-    }
-}
-
-
-declare module BABYLON.GLTF2.Extensions {
-    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
      */
     class MSFT_lod implements IGLTFLoaderExtension {
@@ -1580,6 +1561,38 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
+     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+     */
+    class MSFT_audio_emitter implements IGLTFLoaderExtension {
+        /** The name of this extension. */
+        readonly name: string;
+        /** Defines whether this extension is enabled. */
+        enabled: boolean;
+        private _loader;
+        private _clips;
+        private _emitters;
+        /** @hidden */
+        constructor(loader: GLTFLoader);
+        /** @hidden */
+        dispose(): void;
+        /** @hidden */
+        onLoading(): void;
+        /** @hidden */
+        loadSceneAsync(context: string, scene: ILoaderScene): Nullable<Promise<void>>;
+        /** @hidden */
+        loadNodeAsync(context: string, node: ILoaderNode, assign: (babylonMesh: Mesh) => void): Nullable<Promise<Mesh>>;
+        /** @hidden */
+        loadAnimationAsync(context: string, animation: ILoaderAnimation): Nullable<Promise<AnimationGroup>>;
+        private _loadClipAsync;
+        private _loadEmitterAsync;
+        private _getEventAction;
+        private _loadAnimationEventAsync;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
      */
     class KHR_draco_mesh_compression implements IGLTFLoaderExtension {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 466 - 411
dist/preview release/loaders/babylon.glTFFileLoader.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 6 - 6
dist/preview release/loaders/babylon.objFileLoader.d.ts

@@ -65,10 +65,10 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -80,20 +80,20 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<AssetContainer>;
         /**
          * Read the OBJ file and create an Array of meshes.
          * Each mesh contains all information given by the OBJ and the MTL file.

+ 6 - 6
dist/preview release/loaders/babylon.objFileLoader.js

@@ -258,10 +258,10 @@ var BABYLON;
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        OBJFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fullName) {
+        OBJFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fileName) {
             //get the meshes from OBJ file
             return this._parseSolid(meshesNames, scene, data, rootUrl).then(function (meshes) {
                 return {
@@ -278,10 +278,10 @@ var BABYLON;
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        OBJFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fullName) {
+        OBJFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fileName) {
             //Get the 3D model
             return this.importMeshAsync(null, scene, data, rootUrl, onProgress).then(function () {
                 // return void
@@ -293,10 +293,10 @@ var BABYLON;
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
-         * @param fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        OBJFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fullName) {
+        OBJFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fileName) {
             return this.importMeshAsync(null, scene, data, rootUrl).then(function (result) {
                 var container = new BABYLON.AssetContainer(scene);
                 result.meshes.forEach(function (mesh) { return container.meshes.push(mesh); });

+ 80 - 67
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -83,10 +83,10 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -98,20 +98,20 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<AssetContainer>;
         /**
          * Read the OBJ file and create an Array of meshes.
          * Each mesh contains all information given by the OBJ and the MTL file.
@@ -129,6 +129,7 @@ declare module BABYLON {
 }
 
 
+
 declare module BABYLON {
     /**
      * Mode that determines the coordinate system to use.
@@ -165,11 +166,11 @@ declare module BABYLON {
      */
     interface IGLTFLoaderData {
         /**
-         * JSON that represents the glTF.
+         * Object that represents the glTF JSON.
          */
         json: Object;
         /**
-         * The BIN chunk of a binary glTF
+         * The BIN chunk of a binary glTF.
          */
         bin: Nullable<ArrayBufferView>;
     }
@@ -206,13 +207,13 @@ declare module BABYLON {
     /** @hidden */
     interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
     /**
      * File loader for loading glTF files into a scene.
@@ -270,8 +271,6 @@ declare module BABYLON {
          * If true, no extra effects are applied to transparent pixels.
          */
         transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
         /**
          * Function called before loading a url referenced by the asset.
          */
@@ -354,15 +353,6 @@ declare module BABYLON {
          */
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         /**
-         * Returns a promise that resolves when the asset is completely loaded.
-         * @returns a promise that resolves when the asset is completely loaded.
-         */
-        whenCompleteAsync(): Promise<void>;
-        /**
-         * The loader state or null if the loader is not active.
-         */
-        readonly loaderState: Nullable<GLTFLoaderState>;
-        /**
          * Defines if the loader logging is enabled.
          */
         loggingEnabled: boolean;
@@ -370,6 +360,19 @@ declare module BABYLON {
          * Defines if the loader should capture performance counters.
          */
         capturePerformanceCounters: boolean;
+        /**
+         * Defines if the loader should validate the asset.
+         */
+        validate: boolean;
+        /**
+         * Observable raised after validation when validate is set to true. The event data is the result of the validation.
+         */
+        readonly onValidatedObservable: Observable<IGLTFValidationResults>;
+        private _onValidatedObserver;
+        /**
+         * Callback raised after a loader extension is created.
+         */
+        onValidated: (results: IGLTFValidationResults) => void;
         private _loader;
         /**
          * Name of the loader ("gltf")
@@ -392,10 +395,10 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -407,20 +410,20 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<AssetContainer>;
         /**
          * If the data string can be loaded directly.
          * @param data string contianing the file data
@@ -436,11 +439,21 @@ declare module BABYLON {
          * @returns the created plugin
          */
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
-        private _parse;
+        /**
+         * The loader state or null if the loader is not active.
+         */
+        readonly loaderState: Nullable<GLTFLoaderState>;
+        /**
+         * Returns a promise that resolves when the asset is completely loaded.
+         * @returns a promise that resolves when the asset is completely loaded.
+         */
+        whenCompleteAsync(): Promise<void>;
+        private _parseAsync;
+        private _validateAsync;
         private _getLoader;
-        private _parseBinary;
-        private _parseV1;
-        private _parseV2;
+        private _unpackBinary;
+        private _unpackBinaryV1;
+        private _unpackBinaryV2;
         private static _parseVersion;
         private static _compareVersion;
         private static _decodeBufferToText;
@@ -1030,7 +1043,6 @@ declare module BABYLON.GLTF1 {
 }
 
 
-
 declare module BABYLON.GLTF2 {
     /**
      * Loader interface with an index field.
@@ -1263,7 +1275,8 @@ declare module BABYLON.GLTF2 {
         private _state;
         private _extensions;
         private _rootUrl;
-        private _fullName;
+        private _fileName;
+        private _uniqueRootUrl;
         private _rootBabylonMesh;
         private _defaultBabylonMaterialData;
         private _progressCallback?;
@@ -1292,14 +1305,14 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
         /** @hidden */
-        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         private _loadAsync;
         private _loadData;
         private _setupData;
@@ -1599,38 +1612,6 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
-     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
-     */
-    class MSFT_audio_emitter implements IGLTFLoaderExtension {
-        /** The name of this extension. */
-        readonly name: string;
-        /** Defines whether this extension is enabled. */
-        enabled: boolean;
-        private _loader;
-        private _clips;
-        private _emitters;
-        /** @hidden */
-        constructor(loader: GLTFLoader);
-        /** @hidden */
-        dispose(): void;
-        /** @hidden */
-        onLoading(): void;
-        /** @hidden */
-        loadSceneAsync(context: string, scene: ILoaderScene): Nullable<Promise<void>>;
-        /** @hidden */
-        loadNodeAsync(context: string, node: ILoaderNode, assign: (babylonMesh: Mesh) => void): Nullable<Promise<Mesh>>;
-        /** @hidden */
-        loadAnimationAsync(context: string, animation: ILoaderAnimation): Nullable<Promise<AnimationGroup>>;
-        private _loadClipAsync;
-        private _loadEmitterAsync;
-        private _getEventAction;
-        private _loadAnimationEventAsync;
-    }
-}
-
-
-declare module BABYLON.GLTF2.Extensions {
-    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
      */
     class MSFT_lod implements IGLTFLoaderExtension {
@@ -1710,6 +1691,38 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
+     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+     */
+    class MSFT_audio_emitter implements IGLTFLoaderExtension {
+        /** The name of this extension. */
+        readonly name: string;
+        /** Defines whether this extension is enabled. */
+        enabled: boolean;
+        private _loader;
+        private _clips;
+        private _emitters;
+        /** @hidden */
+        constructor(loader: GLTFLoader);
+        /** @hidden */
+        dispose(): void;
+        /** @hidden */
+        onLoading(): void;
+        /** @hidden */
+        loadSceneAsync(context: string, scene: ILoaderScene): Nullable<Promise<void>>;
+        /** @hidden */
+        loadNodeAsync(context: string, node: ILoaderNode, assign: (babylonMesh: Mesh) => void): Nullable<Promise<Mesh>>;
+        /** @hidden */
+        loadAnimationAsync(context: string, animation: ILoaderAnimation): Nullable<Promise<AnimationGroup>>;
+        private _loadClipAsync;
+        private _loadEmitterAsync;
+        private _getEventAction;
+        private _loadAnimationEventAsync;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
      */
     class KHR_draco_mesh_compression implements IGLTFLoaderExtension {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 472 - 417
dist/preview release/loaders/babylonjs.loaders.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


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

@@ -90,10 +90,10 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -105,20 +105,20 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<AssetContainer>;
         /**
          * Read the OBJ file and create an Array of meshes.
          * Each mesh contains all information given by the OBJ and the MTL file.
@@ -136,6 +136,7 @@ declare module BABYLON {
 }
 
 
+
 declare module BABYLON {
     /**
      * Mode that determines the coordinate system to use.
@@ -172,11 +173,11 @@ declare module BABYLON {
      */
     interface IGLTFLoaderData {
         /**
-         * JSON that represents the glTF.
+         * Object that represents the glTF JSON.
          */
         json: Object;
         /**
-         * The BIN chunk of a binary glTF
+         * The BIN chunk of a binary glTF.
          */
         bin: Nullable<ArrayBufferView>;
     }
@@ -213,13 +214,13 @@ declare module BABYLON {
     /** @hidden */
     interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
     /**
      * File loader for loading glTF files into a scene.
@@ -277,8 +278,6 @@ declare module BABYLON {
          * If true, no extra effects are applied to transparent pixels.
          */
         transparencyAsCoverage: boolean;
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
         /**
          * Function called before loading a url referenced by the asset.
          */
@@ -361,15 +360,6 @@ declare module BABYLON {
          */
         onExtensionLoaded: (extension: IGLTFLoaderExtension) => void;
         /**
-         * Returns a promise that resolves when the asset is completely loaded.
-         * @returns a promise that resolves when the asset is completely loaded.
-         */
-        whenCompleteAsync(): Promise<void>;
-        /**
-         * The loader state or null if the loader is not active.
-         */
-        readonly loaderState: Nullable<GLTFLoaderState>;
-        /**
          * Defines if the loader logging is enabled.
          */
         loggingEnabled: boolean;
@@ -377,6 +367,19 @@ declare module BABYLON {
          * Defines if the loader should capture performance counters.
          */
         capturePerformanceCounters: boolean;
+        /**
+         * Defines if the loader should validate the asset.
+         */
+        validate: boolean;
+        /**
+         * Observable raised after validation when validate is set to true. The event data is the result of the validation.
+         */
+        readonly onValidatedObservable: Observable<IGLTFValidationResults>;
+        private _onValidatedObserver;
+        /**
+         * Callback raised after a loader extension is created.
+         */
+        onValidated: (results: IGLTFValidationResults) => void;
         private _loader;
         /**
          * Name of the loader ("gltf")
@@ -399,10 +402,10 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
@@ -414,20 +417,20 @@ declare module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns a promise which completes when objects have been loaded to the scene
          */
-        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<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 fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer>;
+        loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<AssetContainer>;
         /**
          * If the data string can be loaded directly.
          * @param data string contianing the file data
@@ -443,11 +446,21 @@ declare module BABYLON {
          * @returns the created plugin
          */
         createPlugin(): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
-        private _parse;
+        /**
+         * The loader state or null if the loader is not active.
+         */
+        readonly loaderState: Nullable<GLTFLoaderState>;
+        /**
+         * Returns a promise that resolves when the asset is completely loaded.
+         * @returns a promise that resolves when the asset is completely loaded.
+         */
+        whenCompleteAsync(): Promise<void>;
+        private _parseAsync;
+        private _validateAsync;
         private _getLoader;
-        private _parseBinary;
-        private _parseV1;
-        private _parseV2;
+        private _unpackBinary;
+        private _unpackBinaryV1;
+        private _unpackBinaryV2;
         private static _parseVersion;
         private static _compareVersion;
         private static _decodeBufferToText;
@@ -1037,7 +1050,6 @@ declare module BABYLON.GLTF1 {
 }
 
 
-
 declare module BABYLON.GLTF2 {
     /**
      * Loader interface with an index field.
@@ -1270,7 +1282,8 @@ declare module BABYLON.GLTF2 {
         private _state;
         private _extensions;
         private _rootUrl;
-        private _fullName;
+        private _fileName;
+        private _uniqueRootUrl;
         private _rootBabylonMesh;
         private _defaultBabylonMaterialData;
         private _progressCallback?;
@@ -1299,14 +1312,14 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{
+        importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{
             meshes: AbstractMesh[];
             particleSystems: IParticleSystem[];
             skeletons: Skeleton[];
             animationGroups: AnimationGroup[];
         }>;
         /** @hidden */
-        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void>;
+        loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         private _loadAsync;
         private _loadData;
         private _setupData;
@@ -1606,38 +1619,6 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
-     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
-     */
-    class MSFT_audio_emitter implements IGLTFLoaderExtension {
-        /** The name of this extension. */
-        readonly name: string;
-        /** Defines whether this extension is enabled. */
-        enabled: boolean;
-        private _loader;
-        private _clips;
-        private _emitters;
-        /** @hidden */
-        constructor(loader: GLTFLoader);
-        /** @hidden */
-        dispose(): void;
-        /** @hidden */
-        onLoading(): void;
-        /** @hidden */
-        loadSceneAsync(context: string, scene: ILoaderScene): Nullable<Promise<void>>;
-        /** @hidden */
-        loadNodeAsync(context: string, node: ILoaderNode, assign: (babylonMesh: Mesh) => void): Nullable<Promise<Mesh>>;
-        /** @hidden */
-        loadAnimationAsync(context: string, animation: ILoaderAnimation): Nullable<Promise<AnimationGroup>>;
-        private _loadClipAsync;
-        private _loadEmitterAsync;
-        private _getEventAction;
-        private _loadAnimationEventAsync;
-    }
-}
-
-
-declare module BABYLON.GLTF2.Extensions {
-    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
      */
     class MSFT_lod implements IGLTFLoaderExtension {
@@ -1717,6 +1698,38 @@ declare module BABYLON.GLTF2.Extensions {
 
 declare module BABYLON.GLTF2.Extensions {
     /**
+     * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
+     */
+    class MSFT_audio_emitter implements IGLTFLoaderExtension {
+        /** The name of this extension. */
+        readonly name: string;
+        /** Defines whether this extension is enabled. */
+        enabled: boolean;
+        private _loader;
+        private _clips;
+        private _emitters;
+        /** @hidden */
+        constructor(loader: GLTFLoader);
+        /** @hidden */
+        dispose(): void;
+        /** @hidden */
+        onLoading(): void;
+        /** @hidden */
+        loadSceneAsync(context: string, scene: ILoaderScene): Nullable<Promise<void>>;
+        /** @hidden */
+        loadNodeAsync(context: string, node: ILoaderNode, assign: (babylonMesh: Mesh) => void): Nullable<Promise<Mesh>>;
+        /** @hidden */
+        loadAnimationAsync(context: string, animation: ILoaderAnimation): Nullable<Promise<AnimationGroup>>;
+        private _loadClipAsync;
+        private _loadEmitterAsync;
+        private _getEventAction;
+        private _loadAnimationEventAsync;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
      */
     class KHR_draco_mesh_compression implements IGLTFLoaderExtension {

+ 125 - 15
dist/preview release/serializers/babylon.glTF2Serializer.d.ts

@@ -14,6 +14,10 @@ declare module BABYLON {
          * 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.
@@ -28,6 +32,8 @@ declare module BABYLON {
          * as keys and their data and paths as values
          */
         static GLTFAsync(scene: Scene, filePrefix: string, options?: IExportOptions): Promise<GLTFData>;
+        private static _PreExportAsync;
+        private static _PostExportAsync;
         /**
          * Exports the geometry of the scene to .glb file format asychronously
          * @param scene Babylon scene with scene hierarchy information
@@ -40,7 +46,7 @@ declare module BABYLON {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * Converts Babylon Scene into glTF 2.0.
      * @hidden
@@ -49,11 +55,11 @@ declare module BABYLON.GLTF2 {
         /**
          * Stores all generated buffer views, which represents views into the main glTF buffer data
          */
-        private _bufferViews;
+        _bufferViews: IBufferView[];
         /**
          * Stores all the generated accessors, which is used for accessing the data within the buffer views in glTF
          */
-        private _accessors;
+        _accessors: IAccessor[];
         /**
          * Stores all the generated nodes, which contains transform and/or mesh information per node
          */
@@ -131,7 +137,19 @@ declare module BABYLON.GLTF2 {
          */
         private _shouldExportTransformNode;
         private _localEngine;
-        private _glTFMaterialExporter;
+        _glTFMaterialExporter: _GLTFMaterialExporter;
+        private _extensions;
+        private _extensionsUsed;
+        private _extensionsRequired;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
+        private _applyExtensions;
+        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<BaseTexture>>;
+        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
+        /**
+         * Load glTF serializer extensions
+         */
+        private _loadExtensions;
         /**
          * Creates a glTF Exporter instance, which can accept optional exporter options
          * @param babylonScene Babylon scene object
@@ -139,6 +157,18 @@ declare module BABYLON.GLTF2 {
          */
         constructor(babylonScene: Scene, options?: IExportOptions);
         /**
+         * Registers a glTF exporter extension
+         * @param name Name of the extension to export
+         * @param factory The factory function that creates the exporter extension
+         */
+        static RegisterExtension(name: string, factory: (exporter: _Exporter) => IGLTFExporterExtension): void;
+        /**
+         * Un-registers an exporter extension
+         * @param name The name fo the exporter extension
+         * @returns A boolean indicating whether the extension has been un-registered
+         */
+        static UnregisterExtension(name: string): boolean;
+        /**
          * Lazy load a local engine with premultiplied alpha set to false
          */
         _getLocalEngine(): Engine;
@@ -208,7 +238,7 @@ declare module BABYLON.GLTF2 {
          * @param binaryWriter The buffer to write the binary data to
          * @param indices Used to specify the order of the vertex data
          */
-        private writeAttributeData;
+        writeAttributeData(vertexBufferKind: string, meshAttributeArray: FloatArray, byteStride: number, binaryWriter: _BinaryWriter): void;
         /**
          * Generates glTF json data
          * @param shouldUseGlb Indicates whether the json should be written for a glb file
@@ -279,7 +309,7 @@ declare module BABYLON.GLTF2 {
          * @param babylonTransformNode Babylon mesh to get the primitive attribute data from
          * @param binaryWriter Buffer to write the attribute data to
          */
-        private setPrimitiveAttributes;
+        private setPrimitiveAttributesAsync;
         /**
          * Creates a glTF scene based on the array of meshes
          * Returns the the total byte offset
@@ -295,14 +325,14 @@ declare module BABYLON.GLTF2 {
          * @param binaryWriter Buffer to write binary data to
          * @returns Node mapping of unique id to index
          */
-        private createNodeMapAndAnimations;
+        private createNodeMapAndAnimationsAsync;
         /**
          * Creates a glTF node from a Babylon mesh
          * @param babylonMesh Source Babylon mesh
          * @param binaryWriter Buffer for storing geometry data
          * @returns glTF node
          */
-        private createNode;
+        private createNodeAsync;
     }
     /**
      * @hidden
@@ -396,7 +426,7 @@ declare module BABYLON {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * Utility methods for working with glTF material conversion properties.  This class should only be used internally
      * @hidden
@@ -600,12 +630,10 @@ declare module BABYLON.GLTF2 {
          * Extracts a texture from a Babylon texture into file data and glTF data
          * @param babylonTexture Babylon texture to extract
          * @param mimeType Mime Type of the babylonTexture
-         * @param images Array of glTF images
-         * @param textures Array of glTF textures
-         * @param imageData map of image file name and data
          * @return glTF texture info, or null if the texture format is not supported
          */
-        private _exportTextureAsync;
+        _exportTextureAsync(babylonTexture: BaseTexture, mimeType: ImageMimeType): Promise<Nullable<ITextureInfo>>;
+        _exportTextureInfoAsync(babylonTexture: BaseTexture, mimeType: ImageMimeType): Promise<Nullable<ITextureInfo>>;
         /**
          * Builds a texture from base64 string
          * @param base64Texture base64 texture string
@@ -621,7 +649,7 @@ declare module BABYLON.GLTF2 {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * @hidden
      * Interface to store animation data.
@@ -797,7 +825,7 @@ declare module BABYLON.GLTF2 {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * @hidden
      */
@@ -891,3 +919,85 @@ declare module BABYLON.GLTF2 {
         static _NormalizeTangentFromRef(tangent: Vector4): void;
     }
 }
+
+
+declare module BABYLON.GLTF2.Exporter {
+    /**
+     * Interface for a glTF exporter extension
+     * @hidden
+     */
+    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>>;
+    }
+}
+/**
+ * Defines the module for the built-in glTF 2.0 exporter extensions.
+ */
+declare module BABYLON.GLTF2.Extensions {
+}
+
+
+declare module BABYLON {
+    /**
+     * Interface for extending the exporter
+     * @hidden
+     */
+    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;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Exporter.Extensions {
+    /**
+     * @hidden
+     */
+    class KHR_texture_transform implements IGLTFExporterExtension {
+        /** Name of this extension */
+        readonly name: string;
+        /** Defines whether this extension is enabled */
+        enabled: boolean;
+        /** Defines whether this extension is required */
+        required: boolean;
+        /** Reference to the glTF exporter */
+        private _exporter;
+        constructor(exporter: _Exporter);
+        dispose(): void;
+        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<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
+         */
+        textureTransformTextureAsync(babylonTexture: Texture, offset: Vector2, rotation: number, scale: Vector2, scene: Scene): Promise<BaseTexture>;
+    }
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3086 - 2825
dist/preview release/serializers/babylon.glTF2Serializer.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


+ 125 - 15
dist/preview release/serializers/babylonjs.serializers.d.ts

@@ -22,6 +22,10 @@ declare module BABYLON {
          * 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.
@@ -36,6 +40,8 @@ declare module BABYLON {
          * as keys and their data and paths as values
          */
         static GLTFAsync(scene: Scene, filePrefix: string, options?: IExportOptions): Promise<GLTFData>;
+        private static _PreExportAsync;
+        private static _PostExportAsync;
         /**
          * Exports the geometry of the scene to .glb file format asychronously
          * @param scene Babylon scene with scene hierarchy information
@@ -48,7 +54,7 @@ declare module BABYLON {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * Converts Babylon Scene into glTF 2.0.
      * @hidden
@@ -57,11 +63,11 @@ declare module BABYLON.GLTF2 {
         /**
          * Stores all generated buffer views, which represents views into the main glTF buffer data
          */
-        private _bufferViews;
+        _bufferViews: IBufferView[];
         /**
          * Stores all the generated accessors, which is used for accessing the data within the buffer views in glTF
          */
-        private _accessors;
+        _accessors: IAccessor[];
         /**
          * Stores all the generated nodes, which contains transform and/or mesh information per node
          */
@@ -139,7 +145,19 @@ declare module BABYLON.GLTF2 {
          */
         private _shouldExportTransformNode;
         private _localEngine;
-        private _glTFMaterialExporter;
+        _glTFMaterialExporter: _GLTFMaterialExporter;
+        private _extensions;
+        private _extensionsUsed;
+        private _extensionsRequired;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
+        private _applyExtensions;
+        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<BaseTexture>>;
+        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
+        /**
+         * Load glTF serializer extensions
+         */
+        private _loadExtensions;
         /**
          * Creates a glTF Exporter instance, which can accept optional exporter options
          * @param babylonScene Babylon scene object
@@ -147,6 +165,18 @@ declare module BABYLON.GLTF2 {
          */
         constructor(babylonScene: Scene, options?: IExportOptions);
         /**
+         * Registers a glTF exporter extension
+         * @param name Name of the extension to export
+         * @param factory The factory function that creates the exporter extension
+         */
+        static RegisterExtension(name: string, factory: (exporter: _Exporter) => IGLTFExporterExtension): void;
+        /**
+         * Un-registers an exporter extension
+         * @param name The name fo the exporter extension
+         * @returns A boolean indicating whether the extension has been un-registered
+         */
+        static UnregisterExtension(name: string): boolean;
+        /**
          * Lazy load a local engine with premultiplied alpha set to false
          */
         _getLocalEngine(): Engine;
@@ -216,7 +246,7 @@ declare module BABYLON.GLTF2 {
          * @param binaryWriter The buffer to write the binary data to
          * @param indices Used to specify the order of the vertex data
          */
-        private writeAttributeData;
+        writeAttributeData(vertexBufferKind: string, meshAttributeArray: FloatArray, byteStride: number, binaryWriter: _BinaryWriter): void;
         /**
          * Generates glTF json data
          * @param shouldUseGlb Indicates whether the json should be written for a glb file
@@ -287,7 +317,7 @@ declare module BABYLON.GLTF2 {
          * @param babylonTransformNode Babylon mesh to get the primitive attribute data from
          * @param binaryWriter Buffer to write the attribute data to
          */
-        private setPrimitiveAttributes;
+        private setPrimitiveAttributesAsync;
         /**
          * Creates a glTF scene based on the array of meshes
          * Returns the the total byte offset
@@ -303,14 +333,14 @@ declare module BABYLON.GLTF2 {
          * @param binaryWriter Buffer to write binary data to
          * @returns Node mapping of unique id to index
          */
-        private createNodeMapAndAnimations;
+        private createNodeMapAndAnimationsAsync;
         /**
          * Creates a glTF node from a Babylon mesh
          * @param babylonMesh Source Babylon mesh
          * @param binaryWriter Buffer for storing geometry data
          * @returns glTF node
          */
-        private createNode;
+        private createNodeAsync;
     }
     /**
      * @hidden
@@ -404,7 +434,7 @@ declare module BABYLON {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * Utility methods for working with glTF material conversion properties.  This class should only be used internally
      * @hidden
@@ -608,12 +638,10 @@ declare module BABYLON.GLTF2 {
          * Extracts a texture from a Babylon texture into file data and glTF data
          * @param babylonTexture Babylon texture to extract
          * @param mimeType Mime Type of the babylonTexture
-         * @param images Array of glTF images
-         * @param textures Array of glTF textures
-         * @param imageData map of image file name and data
          * @return glTF texture info, or null if the texture format is not supported
          */
-        private _exportTextureAsync;
+        _exportTextureAsync(babylonTexture: BaseTexture, mimeType: ImageMimeType): Promise<Nullable<ITextureInfo>>;
+        _exportTextureInfoAsync(babylonTexture: BaseTexture, mimeType: ImageMimeType): Promise<Nullable<ITextureInfo>>;
         /**
          * Builds a texture from base64 string
          * @param base64Texture base64 texture string
@@ -629,7 +657,7 @@ declare module BABYLON.GLTF2 {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * @hidden
      * Interface to store animation data.
@@ -805,7 +833,7 @@ declare module BABYLON.GLTF2 {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * @hidden
      */
@@ -899,3 +927,85 @@ declare module BABYLON.GLTF2 {
         static _NormalizeTangentFromRef(tangent: Vector4): void;
     }
 }
+
+
+declare module BABYLON.GLTF2.Exporter {
+    /**
+     * Interface for a glTF exporter extension
+     * @hidden
+     */
+    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>>;
+    }
+}
+/**
+ * Defines the module for the built-in glTF 2.0 exporter extensions.
+ */
+declare module BABYLON.GLTF2.Extensions {
+}
+
+
+declare module BABYLON {
+    /**
+     * Interface for extending the exporter
+     * @hidden
+     */
+    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;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Exporter.Extensions {
+    /**
+     * @hidden
+     */
+    class KHR_texture_transform implements IGLTFExporterExtension {
+        /** Name of this extension */
+        readonly name: string;
+        /** Defines whether this extension is enabled */
+        enabled: boolean;
+        /** Defines whether this extension is required */
+        required: boolean;
+        /** Reference to the glTF exporter */
+        private _exporter;
+        constructor(exporter: _Exporter);
+        dispose(): void;
+        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<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
+         */
+        textureTransformTextureAsync(babylonTexture: Texture, offset: Vector2, rotation: number, scale: Vector2, scene: Scene): Promise<BaseTexture>;
+    }
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3086 - 2825
dist/preview release/serializers/babylonjs.serializers.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


+ 125 - 15
dist/preview release/serializers/babylonjs.serializers.module.d.ts

@@ -29,6 +29,10 @@ declare module BABYLON {
          * 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.
@@ -43,6 +47,8 @@ declare module BABYLON {
          * as keys and their data and paths as values
          */
         static GLTFAsync(scene: Scene, filePrefix: string, options?: IExportOptions): Promise<GLTFData>;
+        private static _PreExportAsync;
+        private static _PostExportAsync;
         /**
          * Exports the geometry of the scene to .glb file format asychronously
          * @param scene Babylon scene with scene hierarchy information
@@ -55,7 +61,7 @@ declare module BABYLON {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * Converts Babylon Scene into glTF 2.0.
      * @hidden
@@ -64,11 +70,11 @@ declare module BABYLON.GLTF2 {
         /**
          * Stores all generated buffer views, which represents views into the main glTF buffer data
          */
-        private _bufferViews;
+        _bufferViews: IBufferView[];
         /**
          * Stores all the generated accessors, which is used for accessing the data within the buffer views in glTF
          */
-        private _accessors;
+        _accessors: IAccessor[];
         /**
          * Stores all the generated nodes, which contains transform and/or mesh information per node
          */
@@ -146,7 +152,19 @@ declare module BABYLON.GLTF2 {
          */
         private _shouldExportTransformNode;
         private _localEngine;
-        private _glTFMaterialExporter;
+        _glTFMaterialExporter: _GLTFMaterialExporter;
+        private _extensions;
+        private _extensionsUsed;
+        private _extensionsRequired;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
+        private _applyExtensions;
+        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<BaseTexture>>;
+        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
+        /**
+         * Load glTF serializer extensions
+         */
+        private _loadExtensions;
         /**
          * Creates a glTF Exporter instance, which can accept optional exporter options
          * @param babylonScene Babylon scene object
@@ -154,6 +172,18 @@ declare module BABYLON.GLTF2 {
          */
         constructor(babylonScene: Scene, options?: IExportOptions);
         /**
+         * Registers a glTF exporter extension
+         * @param name Name of the extension to export
+         * @param factory The factory function that creates the exporter extension
+         */
+        static RegisterExtension(name: string, factory: (exporter: _Exporter) => IGLTFExporterExtension): void;
+        /**
+         * Un-registers an exporter extension
+         * @param name The name fo the exporter extension
+         * @returns A boolean indicating whether the extension has been un-registered
+         */
+        static UnregisterExtension(name: string): boolean;
+        /**
          * Lazy load a local engine with premultiplied alpha set to false
          */
         _getLocalEngine(): Engine;
@@ -223,7 +253,7 @@ declare module BABYLON.GLTF2 {
          * @param binaryWriter The buffer to write the binary data to
          * @param indices Used to specify the order of the vertex data
          */
-        private writeAttributeData;
+        writeAttributeData(vertexBufferKind: string, meshAttributeArray: FloatArray, byteStride: number, binaryWriter: _BinaryWriter): void;
         /**
          * Generates glTF json data
          * @param shouldUseGlb Indicates whether the json should be written for a glb file
@@ -294,7 +324,7 @@ declare module BABYLON.GLTF2 {
          * @param babylonTransformNode Babylon mesh to get the primitive attribute data from
          * @param binaryWriter Buffer to write the attribute data to
          */
-        private setPrimitiveAttributes;
+        private setPrimitiveAttributesAsync;
         /**
          * Creates a glTF scene based on the array of meshes
          * Returns the the total byte offset
@@ -310,14 +340,14 @@ declare module BABYLON.GLTF2 {
          * @param binaryWriter Buffer to write binary data to
          * @returns Node mapping of unique id to index
          */
-        private createNodeMapAndAnimations;
+        private createNodeMapAndAnimationsAsync;
         /**
          * Creates a glTF node from a Babylon mesh
          * @param babylonMesh Source Babylon mesh
          * @param binaryWriter Buffer for storing geometry data
          * @returns glTF node
          */
-        private createNode;
+        private createNodeAsync;
     }
     /**
      * @hidden
@@ -411,7 +441,7 @@ declare module BABYLON {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * Utility methods for working with glTF material conversion properties.  This class should only be used internally
      * @hidden
@@ -615,12 +645,10 @@ declare module BABYLON.GLTF2 {
          * Extracts a texture from a Babylon texture into file data and glTF data
          * @param babylonTexture Babylon texture to extract
          * @param mimeType Mime Type of the babylonTexture
-         * @param images Array of glTF images
-         * @param textures Array of glTF textures
-         * @param imageData map of image file name and data
          * @return glTF texture info, or null if the texture format is not supported
          */
-        private _exportTextureAsync;
+        _exportTextureAsync(babylonTexture: BaseTexture, mimeType: ImageMimeType): Promise<Nullable<ITextureInfo>>;
+        _exportTextureInfoAsync(babylonTexture: BaseTexture, mimeType: ImageMimeType): Promise<Nullable<ITextureInfo>>;
         /**
          * Builds a texture from base64 string
          * @param base64Texture base64 texture string
@@ -636,7 +664,7 @@ declare module BABYLON.GLTF2 {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * @hidden
      * Interface to store animation data.
@@ -812,7 +840,7 @@ declare module BABYLON.GLTF2 {
 }
 
 
-declare module BABYLON.GLTF2 {
+declare module BABYLON.GLTF2.Exporter {
     /**
      * @hidden
      */
@@ -906,3 +934,85 @@ declare module BABYLON.GLTF2 {
         static _NormalizeTangentFromRef(tangent: Vector4): void;
     }
 }
+
+
+declare module BABYLON.GLTF2.Exporter {
+    /**
+     * Interface for a glTF exporter extension
+     * @hidden
+     */
+    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>>;
+    }
+}
+/**
+ * Defines the module for the built-in glTF 2.0 exporter extensions.
+ */
+declare module BABYLON.GLTF2.Extensions {
+}
+
+
+declare module BABYLON {
+    /**
+     * Interface for extending the exporter
+     * @hidden
+     */
+    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;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Exporter.Extensions {
+    /**
+     * @hidden
+     */
+    class KHR_texture_transform implements IGLTFExporterExtension {
+        /** Name of this extension */
+        readonly name: string;
+        /** Defines whether this extension is enabled */
+        enabled: boolean;
+        /** Defines whether this extension is required */
+        required: boolean;
+        /** Reference to the glTF exporter */
+        private _exporter;
+        constructor(exporter: _Exporter);
+        dispose(): void;
+        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<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
+         */
+        textureTransformTextureAsync(babylonTexture: Texture, offset: Vector2, rotation: number, scale: Vector2, scene: Scene): Promise<BaseTexture>;
+    }
+}

+ 35 - 728
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 3874,
+  "errors": 3753,
   "babylon.typedoc.json": {
-    "errors": 3874,
+    "errors": 3753,
     "AnimationGroup": {
       "Constructor": {
         "new AnimationGroup": {
@@ -1841,11 +1841,6 @@
             "MissingText": true
           }
         },
-        "render": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "renderOcclusionBoundingBox": {
           "Comments": {
             "MissingText": true
@@ -7826,36 +7821,6 @@
                 "MissingText": true
               }
             },
-            "url": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "width": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "height": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "subdivisions": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "minHeight": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "maxHeight": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
             "scene": {
               "Comments": {
                 "MissingText": true
@@ -7865,11 +7830,6 @@
               "Comments": {
                 "MissingText": true
               }
-            },
-            "onReady": {
-              "Comments": {
-                "MissingText": true
-              }
             }
           }
         },
@@ -9948,141 +9908,6 @@
         }
       }
     },
-    "PhysicsEngine": {
-      "Class": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
-      "Constructor": {
-        "new PhysicsEngine": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "gravity": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "_physicsPlugin": {
-              "Comments": {
-                "MissingText": true
-              },
-              "Naming": {
-                "NotCamelCase": true
-              }
-            }
-          }
-        }
-      },
-      "Property": {
-        "gravity": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "Epsilon": {
-          "Comments": {
-            "MissingText": true
-          }
-        }
-      },
-      "Method": {
-        "addJoint": {
-          "Parameter": {
-            "joint": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "dispose": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "getImpostorForPhysicsObject": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "object": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getImpostorWithPhysicsBody": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "body": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getImpostors": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "getPhysicsPlugin": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "getPhysicsPluginName": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "getTimeStep": {
-          "Comments": {
-            "MissingReturn": true
-          }
-        },
-        "removeJoint": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "mainImpostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "connectedImpostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "joint": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setGravity": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "gravity": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        }
-      }
-    },
     "PhysicsGravitationalFieldEvent": {
       "Constructor": {
         "new PhysicsGravitationalFieldEvent": {
@@ -20859,560 +20684,66 @@
         }
       }
     },
-    "IPhysicsEnginePlugin": {
+    "ISceneLoaderPlugin": {
+      "Interface": {
+        "Comments": {
+          "MissingText": true
+        }
+      }
+    },
+    "ISceneLoaderPluginAsync": {
+      "Interface": {
+        "Comments": {
+          "MissingText": true
+        }
+      }
+    },
+    "ISceneLoaderPluginExtensions": {
+      "Interface": {
+        "Comments": {
+          "MissingText": true
+        }
+      }
+    },
+    "ISceneLoaderPluginFactory": {
       "Interface": {
         "Comments": {
           "MissingText": true
         }
       },
       "Property": {
-        "name": {
+        "canDirectLoad": {
           "Comments": {
             "MissingText": true
           }
         },
-        "world": {
+        "name": {
           "Comments": {
             "MissingText": true
           }
         }
       },
       "Method": {
-        "applyForce": {
+        "createPlugin": {
           "Comments": {
             "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "force": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "contactPoint": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
           }
-        },
-        "applyImpulse": {
+        }
+      }
+    },
+    "ISimplificationSettings": {
+      "Property": {
+        "distance": {
           "Comments": {
             "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "force": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "contactPoint": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
           }
         },
-        "dispose": {
+        "optimizeMesh": {
           "Comments": {
             "MissingText": true
           }
         },
-        "executeStep": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "delta": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "impostors": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "generateJoint": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "joint": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "generatePhysicsBody": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getAngularVelocity": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getBodyFriction": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getBodyMass": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getBodyRestitution": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getBoxSizeToRef": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "result": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getLinearVelocity": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getRadius": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "getTimeStep": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "isSupported": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "removeJoint": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "joint": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "removePhysicsBody": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setAngularVelocity": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "velocity": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setBodyFriction": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "friction": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setBodyMass": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "mass": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setBodyRestitution": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "restitution": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setGravity": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "gravity": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setLimit": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "joint": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "upperLimit": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "lowerLimit": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "motorIndex": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setLinearVelocity": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "velocity": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setMotor": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "joint": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "speed": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "maxForce": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "motorIndex": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setPhysicsBodyTransformation": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "newPosition": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "newRotation": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setTimeStep": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "timeStep": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "setTransformationFromPhysicsBody": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "sleepBody": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "syncMeshWithImpostor": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "mesh": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "updateDistanceJoint": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "joint": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "maxDistance": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "minDistance": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "wakeUpBody": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "impostor": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        }
-      }
-    },
-    "ISceneLoaderPlugin": {
-      "Interface": {
-        "Comments": {
-          "MissingText": true
-        }
-      }
-    },
-    "ISceneLoaderPluginAsync": {
-      "Interface": {
-        "Comments": {
-          "MissingText": true
-        }
-      }
-    },
-    "ISceneLoaderPluginExtensions": {
-      "Interface": {
-        "Comments": {
-          "MissingText": true
-        }
-      }
-    },
-    "ISceneLoaderPluginFactory": {
-      "Interface": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
-      "Property": {
-        "canDirectLoad": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "name": {
-          "Comments": {
-            "MissingText": true
-          }
-        }
-      },
-      "Method": {
-        "createPlugin": {
-          "Comments": {
-            "MissingText": true
-          }
-        }
-      }
-    },
-    "ISimplificationSettings": {
-      "Property": {
-        "distance": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "optimizeMesh": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "quality": {
+        "quality": {
           "Comments": {
             "MissingText": true
           }
@@ -21507,30 +20838,6 @@
         }
       }
     },
-    "PhysicsImpostorJoint": {
-      "Interface": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
-      "Property": {
-        "connectedImpostor": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "joint": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "mainImpostor": {
-          "Comments": {
-            "MissingText": true
-          }
-        }
-      }
-    },
     "PhysicsImpostorParameters": {
       "Interface": {
         "Comments": {

+ 15 - 1
dist/preview release/viewer/babylon.viewer.d.ts

@@ -924,7 +924,7 @@ declare module BabylonViewer {
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 declare module BabylonViewer {
@@ -1558,6 +1558,20 @@ declare module BabylonViewer {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 declare module BabylonViewer {
+    /**
+        * A custom upgrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedUpgrade(sceneManager: SceneManager): boolean;
+    /**
+        * A custom degrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedDegrade(sceneManager: SceneManager): boolean;
+}
+declare module BabylonViewer {
 }
 declare module BabylonViewer {
     export interface IEnvironmentMapConfiguration {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


+ 18 - 1
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -985,13 +985,14 @@ declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
 }
 
 declare module 'babylonjs-viewer/optimizer/custom' {
+    import { extendedUpgrade } from "babylonjs-viewer/optimizer/custom/extended";
     import { SceneManager } from "babylonjs-viewer/managers/sceneManager";
     /**
       *
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 
@@ -1662,6 +1663,22 @@ declare module 'babylonjs-viewer/loader/plugins' {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 
+declare module 'babylonjs-viewer/optimizer/custom/extended' {
+    import { SceneManager } from 'babylonjs-viewer/managers/sceneManager';
+    /**
+        * A custom upgrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedUpgrade(sceneManager: SceneManager): boolean;
+    /**
+        * A custom degrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedDegrade(sceneManager: SceneManager): boolean;
+}
+
 declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';

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

@@ -126,6 +126,7 @@
 - Improved performance of cached nodes but ensuring parent always updates cache. This removes failed isSynchronized test that meant computeWorldMatrix would always have to rebuild. On large scenes this could double framerate. ([Bolloxim](https://github.com/Bolloxim))
 - Added FXAA and MSAA support to the StandardRenderingPipeline ([julien-moreau](https://github.com/julien-moreau))
 - Make teleportCamera public in VR experience helper ([TrevorDev](https://github.com/TrevorDev))
+- Added optional alphaFilter parameter to ```CreateGroundFromHeightMap``` to allow for heightmaps to be created that ignore any transparent data ([Postman-nz](https://github.com/Postman-nz))
 
 
 ### glTF Loader
@@ -137,6 +138,7 @@
 - Added support for EXT_lights_imageBased ([bghgary](http://www.github.com/bghgary))
 - Added support for MSFT_audio_emitter ([najadojo](http://www.github.com/najadojo))
 - Added support for custom loader extensions ([bghgary](http://www.github.com/bghgary))
+- Added support for validating assets using [glTF-Validator](https://github.com/KhronosGroup/glTF-Validator) ([bghgary](http://www.github.com/bghgary))
 
 ### glTF Serializer
 - Added support for exporting the scale, rotation and offset texture properties ([kcoley](http://www.github.com/kcoley))

+ 5 - 3
gui/src/2D/controls/control.ts

@@ -1378,9 +1378,11 @@ export class Control {
             this._root = null;
         }
 
-        var index = this._host._linkedControls.indexOf(this);
-        if (index > -1) {
-            this.linkWithMesh(null);
+        if (this._host) {
+            var index = this._host._linkedControls.indexOf(this);
+            if (index > -1) {
+                this.linkWithMesh(null);
+            }
         }
     }
 

+ 9 - 0
inspector/sass/tabs/_gltfTab.scss

@@ -22,6 +22,15 @@
             }
         }
 
+        .gltf-icon {
+            width      : 1em;
+            height     : 1em;
+            line-height: 1em;
+            display    : inline-block;
+            font-family: $font-family-icons;
+            margin-right:10px;
+        }
+
         .gltf-checkbox {
             @extend .gltf-action;
             &:before {

+ 2 - 2
inspector/src/Inspector.ts

@@ -28,7 +28,7 @@ export class Inspector {
     /** The original canvas style, before applying the inspector*/
     private _canvasStyle: any;
 
-    private _initialTab: number;
+    private _initialTab: number | string;
 
     private _parentElement: Nullable<HTMLElement>;
 
@@ -40,7 +40,7 @@ export class Inspector {
      * If the parameter 'popup' is false, the inspector is created as a right panel on the main window.
      * If the parameter 'popup' is true, the inspector is created in another popup.
      */
-    constructor(scene: Scene, popup?: boolean, initialTab: number = 0, parentElement: Nullable<HTMLElement> = null, newColors?: {
+    constructor(scene: Scene, popup?: boolean, initialTab: number | string = 0, parentElement: Nullable<HTMLElement> = null, newColors?: {
         backgroundColor?: string,
         backgroundColorLighter?: string,
         backgroundColorLighter2?: string,

+ 139 - 76
inspector/src/tabs/GLTFTab.ts

@@ -1,4 +1,4 @@
-import { Mesh, NullEngine, PBRMaterial, Scene, SceneLoader, StandardMaterial, Texture, TransformNode } from "babylonjs";
+import { Mesh, Nullable, NullEngine, PBRMaterial, Scene, SceneLoader, StandardMaterial, Texture, TransformNode } from "babylonjs";
 import { GLTF2, GLTFFileLoader } from "babylonjs-loaders";
 import { GLTF2Export } from "babylonjs-serializers";
 import { DetailPanel } from "../details/DetailPanel";
@@ -9,25 +9,17 @@ import { Inspector } from "../Inspector";
 import { Tab } from "./Tab";
 import { TabBar } from "./TabBar";
 
+import "babylonjs-gltf2interface";
 import * as Split from "Split";
 
-interface ILoaderDefaults {
-    [extensionName: string]: {
-        [key: string]: any
-    },
-    extensions: {
-        [extensionName: string]: {
-            [key: string]: any
-        }
-    }
-}
-
 export class GLTFTab extends Tab {
-    private static _LoaderDefaults: ILoaderDefaults | null = null;
+    private static _LoaderDefaults: any = null;
+    private static _ValidationResults: Nullable<IGLTFValidationResults> = null;
+    private static _OnValidationResultsUpdated: Nullable<(results: IGLTFValidationResults) => void> = null;
 
     private _inspector: Inspector;
     private _actions: HTMLDivElement;
-    private _detailsPanel: DetailPanel | null = null;
+    private _detailsPanel: Nullable<DetailPanel> = null;
     private _split: any;
 
     public static get IsSupported(): boolean {
@@ -38,18 +30,14 @@ export class GLTFTab extends Tab {
     public static _Initialize(): void {
         // Must register with OnPluginActivatedObservable as early as possible to override the loader defaults.
         SceneLoader.OnPluginActivatedObservable.add((loader: GLTFFileLoader) => {
-            if (loader.name === "gltf" && GLTFTab._LoaderDefaults) {
-                const defaults = GLTFTab._LoaderDefaults;
-                for (const key in defaults) {
-                    if (key !== "extensions") {
-                        (loader as any)[key] = GLTFTab._LoaderDefaults[key];
-                    }
-                }
+            if (loader.name === "gltf") {
+                GLTFTab._ApplyLoaderDefaults(loader);
+
+                loader.onValidatedObservable.add(results => {
+                    GLTFTab._ValidationResults = results;
 
-                loader.onExtensionLoadedObservable.add(extension => {
-                    const extensionDefaults = defaults.extensions[extension.name];
-                    for (const key in extensionDefaults) {
-                        (extension as any)[key] = extensionDefaults[key];
+                    if (GLTFTab._OnValidationResultsUpdated) {
+                        GLTFTab._OnValidationResultsUpdated(results);
                     }
                 });
             }
@@ -57,12 +45,12 @@ export class GLTFTab extends Tab {
     }
 
     constructor(tabbar: TabBar, inspector: Inspector) {
-        super(tabbar, 'GLTF');
+        super(tabbar, "GLTF");
 
         this._inspector = inspector;
-        this._panel = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
-        this._actions = Helpers.CreateDiv('gltf-actions', this._panel) as HTMLDivElement;
-        this._actions.addEventListener('click', event => {
+        this._panel = Helpers.CreateDiv("tab-panel") as HTMLDivElement;
+        this._actions = Helpers.CreateDiv("gltf-actions", this._panel) as HTMLDivElement;
+        this._actions.addEventListener("click", event => {
             this._closeDetailsPanel();
         });
 
@@ -82,95 +70,170 @@ export class GLTFTab extends Tab {
     }
 
     private _addImport() {
-        const importTitle = Helpers.CreateDiv('gltf-title', this._actions);
-        importTitle.textContent = 'Import';
+        const importTitle = Helpers.CreateDiv("gltf-title", this._actions);
+        importTitle.textContent = "Import";
 
-        const importActions = Helpers.CreateDiv('gltf-actions', this._actions) as HTMLDivElement;
+        const importActions = Helpers.CreateDiv("gltf-actions", this._actions) as HTMLDivElement;
 
-        this._getLoaderDefaultsAsync().then(defaults => {
-            importTitle.addEventListener('click', event => {
+        GLTFTab._GetLoaderDefaultsAsync().then(defaults => {
+            const loaderAction = Helpers.CreateDiv("gltf-action", importActions) as HTMLDivElement;
+            loaderAction.innerText = "Loader";
+            loaderAction.addEventListener("click", event => {
                 this._showLoaderDefaults(defaults);
                 event.stopPropagation();
             });
 
-            importActions.addEventListener('click', event => {
-                this._showLoaderDefaults(defaults);
-                event.stopPropagation();
-            });
-
-            const extensionsTitle = Helpers.CreateDiv('gltf-title', importActions) as HTMLDivElement;
+            const extensionsTitle = Helpers.CreateDiv("gltf-title", importActions) as HTMLDivElement;
             extensionsTitle.textContent = "Extensions";
 
             for (const extensionName in defaults.extensions) {
                 const extensionDefaults = defaults.extensions[extensionName];
 
-                const extensionAction = Helpers.CreateDiv('gltf-action', importActions);
-                extensionAction.addEventListener('click', event => {
+                const extensionAction = Helpers.CreateDiv("gltf-action", importActions);
+                extensionAction.addEventListener("click", event => {
                     if (this._showLoaderExtensionDefaults(extensionDefaults)) {
                         event.stopPropagation();
                     }
                 });
 
-                const checkbox = Helpers.CreateElement('span', 'gltf-checkbox', extensionAction);
+                const checkbox = Helpers.CreateElement("span", "gltf-checkbox", extensionAction);
 
                 if (extensionDefaults.enabled) {
-                    checkbox.classList.add('action', 'active');
+                    checkbox.classList.add("action", "active");
                 }
 
-                checkbox.addEventListener('click', () => {
-                    checkbox.classList.toggle('active');
-                    extensionDefaults.enabled = checkbox.classList.contains('active');
+                checkbox.addEventListener("click", () => {
+                    checkbox.classList.toggle("active");
+                    extensionDefaults.enabled = checkbox.classList.contains("active");
                 });
 
-                const label = Helpers.CreateElement('span', null, extensionAction);
+                const label = Helpers.CreateElement("span", null, extensionAction);
                 label.textContent = extensionName;
             }
+
+            let validationTitle: Nullable<HTMLDivElement> = null;
+            let validationAction: Nullable<HTMLDivElement> = null;
+
+            GLTFTab._OnValidationResultsUpdated = results => {
+                if (!validationTitle) {
+                    validationTitle = Helpers.CreateDiv("gltf-title", importActions) as HTMLDivElement;
+                }
+
+                if (!validationAction) {
+                    validationAction = Helpers.CreateDiv("gltf-action", importActions) as HTMLDivElement;
+                    validationAction.addEventListener("click", event => {
+                        GLTFTab._ShowValidationResults();
+                        event.stopPropagation();
+                    });
+                }
+
+                validationTitle.textContent = results.uri === "null" ? "Validation" : `Validation - ${BABYLON.Tools.GetFilename(results.uri)}`;
+                GLTFTab._FormatValidationResultsShort(validationAction, results);
+            };
+
+            if (GLTFTab._ValidationResults) {
+                GLTFTab._OnValidationResultsUpdated(GLTFTab._ValidationResults);
+            }
         });
     }
 
-    private static _EnumeratePublic(obj: any, callback: (key: string, value: any) => void): void {
+    private static _FormatValidationResultsShort(validationAction: HTMLDivElement, results: IGLTFValidationResults): void {
+        validationAction.innerHTML = "";
+
+        let message = "";
+        const add = (count: number, issueType: string): void => {
+            if (count) {
+                if (message) {
+                    message += ", ";
+                }
+
+                message += count === 1 ? `${count} ${issueType}` : `${count} ${issueType}s`;
+            }
+        };
+
+        const issues = results.issues;
+        add(issues.numErrors, "error");
+        add(issues.numWarnings, "warning");
+        add(issues.numInfos, "info");
+        add(issues.numHints, "hint");
+
+        const actionDiv = Helpers.CreateDiv("gltf-action", validationAction) as HTMLDivElement;
+
+        const iconSpan = Helpers.CreateElement("span", "gltf-icon", actionDiv, issues.numErrors ? "The asset contains errors." : "The asset is valid.");
+        iconSpan.textContent = issues.numErrors ? "\uf057" : "\uf058";
+        iconSpan.style.color = issues.numErrors ? "red" : "green";
+
+        const messageSpan = Helpers.CreateElement("span", "gltf-icon", actionDiv);
+        messageSpan.textContent = message || "No issues";
+    }
+
+    private static _ShowValidationResults(): void {
+        if (GLTFTab._ValidationResults) {
+            const win = window.open("", "_blank");
+            if (win) {
+                // TODO: format this better and use generator registry (https://github.com/KhronosGroup/glTF-Generator-Registry)
+                win.document.title = "glTF Validation Results";
+                win.document.body.innerText = JSON.stringify(GLTFTab._ValidationResults, null, 2);
+                win.document.body.style.whiteSpace = "pre";
+                win.document.body.style.fontFamily = `monospace`;
+                win.document.body.style.fontSize = `14px`;
+                win.focus();
+            }
+        }
+    }
+
+    private static _ApplyLoaderDefaults(loader: GLTFFileLoader): void {
+        const defaults = GLTFTab._LoaderDefaults;
+        if (defaults) {
+            for (const key in defaults) {
+                if (key !== "extensions") {
+                    (loader as any)[key] = defaults[key];
+                }
+            }
+
+            loader.onExtensionLoadedObservable.add(extension => {
+                const extensionDefaults = defaults.extensions[extension.name];
+                for (const key in extensionDefaults) {
+                    (extension as any)[key] = extensionDefaults[key];
+                }
+            });
+        }
+    }
+
+    private static _GetPublic(obj: any): any {
+        const result: any = {};
         for (const key in obj) {
-            if (key !== "name" && key[0] !== '_') {
+            if (key !== "name" && key[0] !== "_") {
                 const value = obj[key];
                 const type = typeof value;
                 if (type !== "object" && type !== "function" && type !== "undefined") {
-                    callback(key, value);
+                    result[key] = value;
                 }
             }
         }
+        return result;
     }
 
-    private _getLoaderDefaultsAsync(): Promise<ILoaderDefaults> {
+    /** @hidden */
+    public static _GetLoaderDefaultsAsync(): Promise<any> {
         if (GLTFTab._LoaderDefaults) {
             return Promise.resolve(GLTFTab._LoaderDefaults);
         }
 
-        const defaults: ILoaderDefaults = {
-            extensions: {}
-        };
-
         const engine = new NullEngine();
         const scene = new Scene(engine);
-
         const loader = new GLTFFileLoader();
-        GLTFTab._EnumeratePublic(loader, (key, value) => {
-            defaults[key] = value;
-        });
 
+        GLTFTab._LoaderDefaults = GLTFTab._GetPublic(loader);
+        GLTFTab._LoaderDefaults.extensions = {};
         loader.onExtensionLoadedObservable.add(extension => {
-            const extensionDefaults: any = {};
-            GLTFTab._EnumeratePublic(extension, (key, value) => {
-                extensionDefaults[key] = value;
-            });
-            defaults.extensions[extension.name] = extensionDefaults;
+            GLTFTab._LoaderDefaults.extensions[extension.name] = GLTFTab._GetPublic(extension);
         });
 
         const data = '{ "asset": { "version": "2.0" } }';
         return loader.importMeshAsync([], scene, data, "").then(() => {
-            scene.dispose();
             engine.dispose();
-
-            return (GLTFTab._LoaderDefaults = defaults);
+            return GLTFTab._LoaderDefaults;
         });
     }
 
@@ -182,7 +245,7 @@ export class GLTFTab extends Tab {
             this._split = Split([this._actions, this._detailsPanel.toHtml()], {
                 blockDrag: this._inspector.popupMode,
                 sizes: [50, 50],
-                direction: 'vertical'
+                direction: "vertical"
             });
         }
 
@@ -232,17 +295,17 @@ export class GLTFTab extends Tab {
     }
 
     private _addExport() {
-        const exportTitle = Helpers.CreateDiv('gltf-title', this._actions);
-        exportTitle.textContent = 'Export';
+        const exportTitle = Helpers.CreateDiv("gltf-title", this._actions);
+        exportTitle.textContent = "Export";
 
-        const exportActions = Helpers.CreateDiv('gltf-actions', this._actions) as HTMLDivElement;
+        const exportActions = Helpers.CreateDiv("gltf-actions", this._actions) as HTMLDivElement;
 
-        const name = Helpers.CreateInput('gltf-input', exportActions);
+        const name = Helpers.CreateInput("gltf-input", exportActions);
         name.placeholder = "File name...";
 
-        const button = Helpers.CreateElement('button', 'gltf-button', exportActions) as HTMLButtonElement;
-        button.innerText = 'Export GLB';
-        button.addEventListener('click', () => {
+        const button = Helpers.CreateElement("button", "gltf-button", exportActions) as HTMLButtonElement;
+        button.innerText = "Export GLB";
+        button.addEventListener("click", () => {
             GLTF2Export.GLBAsync(this._inspector.scene, name.value || "scene", {
                 shouldExportTransformNode: transformNode => !GLTFTab._IsSkyBox(transformNode)
             }).then((glb) => {

+ 17 - 4
inspector/src/tabs/TabBar.ts

@@ -41,7 +41,7 @@ export class TabBar extends BasicElement {
     /** The list of tabs visible, displayed in the tab bar */
     private _visibleTabs: Array<Tab> = [];
 
-    constructor(inspector: Inspector, initialTab?: number) {
+    constructor(inspector: Inspector, initialTab?: number | string) {
         super();
         this._inspector = inspector;
         this._tabs.push(new SceneTab(this, this._inspector));
@@ -69,9 +69,13 @@ export class TabBar extends BasicElement {
 
         this._build();
 
-        //Check initialTab is defined and between tabs bounds
-        if (!initialTab || initialTab < 0 || initialTab >= this._tabs.length) {
-            initialTab = 0;
+        if (typeof initialTab === "string") {
+            initialTab = this.getTabIndex(initialTab);
+        } else {
+            //Check initialTab is defined and between tabs bounds
+            if (!initialTab || initialTab < 0 || initialTab >= this._tabs.length) {
+                initialTab = 0;
+            }
         }
 
         this._tabs[initialTab].active(true);
@@ -186,6 +190,15 @@ export class TabBar extends BasicElement {
         return 0;
     }
 
+    public getTabIndex(name: string): number {
+        for (let i = 0; i < this._tabs.length; i++) {
+            if (this._tabs[i].name === name) {
+                return i;
+            }
+        }
+        return 0;
+    }
+
     public get inspector(): Inspector {
         return this._inspector;
     }

+ 3 - 0
inspector/tsconfig.json

@@ -28,6 +28,9 @@
             "babylonjs-gui": [
                 "../../dist/preview release/gui/babylon.gui.module.d.ts"
             ],
+            "babylonjs-gltf2interface": [
+                "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"
+            ],
             "babylonjs-loaders": [
                 "../../dist/preview release/loaders/babylonjs.loaders.module.d.ts"
             ],

+ 6 - 0
inspector/webpack.config.js

@@ -39,6 +39,12 @@ module.exports = {
             commonjs2: "babylonjs-gui",
             amd: "babylonjs-gui"
         },
+        "babylonjs-gltf2interface": {
+            root: "BABYLON",
+            commonjs: "babylonjs-gltf2interface",
+            commonjs2: "babylonjs-gltf2interface",
+            amd: "babylonjs-gltf2interface"
+        },
         "babylonjs-loaders": {
             root: "BABYLON",
             commonjs: "babylonjs-loaders",

+ 6 - 6
loaders/src/OBJ/babylon.objFileLoader.ts

@@ -261,10 +261,10 @@ module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @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, fullName?: string): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
+        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 {
@@ -282,10 +282,10 @@ module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @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, fullName?: string): Promise<void> {
+        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
@@ -298,10 +298,10 @@ module BABYLON {
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
-         * @param fullName Defines the FQDN of the file to load
+         * @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, fullName?: string): Promise<AssetContainer> {
+        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));

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

@@ -64,7 +64,8 @@ module BABYLON.GLTF2 {
         private _state: Nullable<GLTFLoaderState> = null;
         private _extensions: { [name: string]: IGLTFLoaderExtension } = {};
         private _rootUrl: string;
-        private _fullName: string;
+        private _fileName: string;
+        private _uniqueRootUrl: string;
         private _rootBabylonMesh: Mesh;
         private _defaultBabylonMaterialData: { [drawMode: number]: Material } = {};
         private _progressCallback?: (event: SceneLoaderProgressEvent) => void;
@@ -157,11 +158,11 @@ module BABYLON.GLTF2 {
         }
 
         /** @hidden */
-        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
+        public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
             return Promise.resolve().then(() => {
                 this.babylonScene = scene;
                 this._rootUrl = rootUrl;
-                this._fullName = fullName || `${Date.now()}`;
+                this._fileName = fileName || "scene";
                 this._progressCallback = onProgress;
                 this._loadData(data);
 
@@ -200,11 +201,11 @@ module BABYLON.GLTF2 {
         }
 
         /** @hidden */
-        public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void> {
+        public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<void> {
             return Promise.resolve().then(() => {
                 this.babylonScene = scene;
                 this._rootUrl = rootUrl;
-                this._fullName = fullName || `${Date.now()}`;
+                this._fileName = fileName || "scene";
                 this._progressCallback = onProgress;
                 this._loadData(data);
                 return this._loadAsync(null, () => undefined);
@@ -213,6 +214,8 @@ module BABYLON.GLTF2 {
 
         private _loadAsync<T>(nodes: Nullable<Array<number>>, resultFunc: () => T): Promise<T> {
             return Promise.resolve().then(() => {
+                this._uniqueRootUrl = (this._rootUrl.indexOf("file:") === -1 && this._fileName) ? this._rootUrl : `${this._rootUrl}${Date.now()}/`;
+
                 this._loadExtensions();
                 this._checkExtensions();
 
@@ -1028,7 +1031,7 @@ module BABYLON.GLTF2 {
             }
 
             return Promise.all(promises).then(() => {
-                babylonAnimationGroup.normalize(this._parent._normalizeAnimationGroupsToBeginAtZero ? 0 : null);
+                babylonAnimationGroup.normalize(0);
                 return babylonAnimationGroup;
             });
         }
@@ -1658,7 +1661,8 @@ module BABYLON.GLTF2 {
 
             const image = ArrayItem.Get(`${context}/source`, this.gltf.images, texture.source);
             promises.push(this.loadImageAsync(`#/images/${image.index}`, image).then(data => {
-                const dataUrl = `data:${this._fullName}${image.uri || `image${image.index}`}`;
+                const name = image.uri || `${this._fileName}#image${image.index}`;
+                const dataUrl = `data:${this._uniqueRootUrl}${name}`;
                 babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
             }));
 

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

@@ -1,5 +1,4 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 module BABYLON.GLTF2 {
     /**

+ 138 - 81
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -1,4 +1,5 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
+/// <reference path="../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 module BABYLON {
     /**
@@ -41,12 +42,12 @@ module BABYLON {
      */
     export interface IGLTFLoaderData {
         /**
-         * JSON that represents the glTF.
+         * Object that represents the glTF JSON.
          */
         json: Object;
 
         /**
-         * The BIN chunk of a binary glTF
+         * The BIN chunk of a binary glTF.
          */
         bin: Nullable<ArrayBufferView>;
     }
@@ -89,8 +90,8 @@ module BABYLON {
     /** @hidden */
     export interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }>;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string) => Promise<void>;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }>;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
 
     /**
@@ -103,7 +104,9 @@ module BABYLON {
         /** @hidden */
         public static _CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
 
-        // #region Common options
+        // --------------
+        // Common options
+        // --------------
 
         /**
          * Raised when the asset has been parsed
@@ -122,9 +125,9 @@ module BABYLON {
             this._onParsedObserver = this.onParsedObservable.add(callback);
         }
 
-        // #endregion
-
-        // #region V1 options
+        // ----------
+        // V1 options
+        // ----------
 
         /**
          * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders.
@@ -141,9 +144,9 @@ module BABYLON {
          */
         public static HomogeneousCoordinates = false;
 
-        // #endregion
-
-        // #region V2 options
+        // ----------
+        // V2 options
+        // ----------
 
         /**
          * The coordinate system mode. Defaults to AUTO.
@@ -177,9 +180,6 @@ module BABYLON {
          */
         public transparencyAsCoverage = false;
 
-        /** @hidden */
-        public _normalizeAnimationGroupsToBeginAtZero = true;
-
         /**
          * Function called before loading a url referenced by the asset.
          */
@@ -327,28 +327,6 @@ module BABYLON {
         }
 
         /**
-         * Returns a promise that resolves when the asset is completely loaded.
-         * @returns a promise that resolves when the asset is completely loaded.
-         */
-        public whenCompleteAsync(): Promise<void> {
-            return new Promise((resolve, reject) => {
-                this.onCompleteObservable.addOnce(() => {
-                    resolve();
-                });
-                this.onErrorObservable.addOnce(reason => {
-                    reject(reason);
-                });
-            });
-        }
-
-        /**
-         * The loader state or null if the loader is not active.
-         */
-        public get loaderState(): Nullable<GLTFLoaderState> {
-            return this._loader ? this._loader.state : null;
-        }
-
-        /**
          * Defines if the loader logging is enabled.
          */
         public get loggingEnabled(): boolean {
@@ -394,7 +372,27 @@ module BABYLON {
             }
         }
 
-        // #endregion
+        /**
+         * Defines if the loader should validate the asset.
+         */
+        public validate = false;
+
+        /**
+         * Observable raised after validation when validate is set to true. The event data is the result of the validation.
+         */
+        public readonly onValidatedObservable = new Observable<IGLTFValidationResults>();
+
+        private _onValidatedObserver: Nullable<Observer<IGLTFValidationResults>>;
+
+        /**
+         * Callback raised after a loader extension is created.
+         */
+        public set onValidated(callback: (results: IGLTFValidationResults) => void) {
+            if (this._onValidatedObserver) {
+                this.onValidatedObservable.remove(this._onValidatedObserver);
+            }
+            this._onValidatedObserver = this.onValidatedObservable.add(callback);
+        }
 
         private _loader: Nullable<IGLTFLoader> = null;
 
@@ -445,14 +443,14 @@ module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @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, fullName?: string): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
-            return Promise.resolve().then(() => {
-                const loaderData = this._parse(data);
+        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[] }> {
+            return this._parseAsync(scene, data, rootUrl, fileName).then(loaderData => {
+                this._log(`Loading ${fileName || ""}`);
                 this._loader = this._getLoader(loaderData);
-                return this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress, fullName);
+                return this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress, fileName);
             });
         }
 
@@ -462,14 +460,14 @@ module BABYLON {
          * @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 fullName Defines the FQDN of the file to load
+         * @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 | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<void> {
-            return Promise.resolve().then(() => {
-                const loaderData = this._parse(data);
+        public loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<void> {
+            return this._parseAsync(scene, data, rootUrl, fileName).then(loaderData => {
+                this._log(`Loading ${fileName || ""}`);
                 this._loader = this._getLoader(loaderData);
-                return this._loader.loadAsync(scene, loaderData, rootUrl, onProgress, fullName);
+                return this._loader.loadAsync(scene, loaderData, rootUrl, onProgress, fileName);
             });
         }
 
@@ -479,14 +477,14 @@ module BABYLON {
          * @param data The data to import
          * @param rootUrl The root url for scene and resources
          * @param onProgress The callback when the load progresses
-         * @param fullName Defines the FQDN of the file to load
+         * @param fileName Defines the name of the file to load
          * @returns The loaded asset container
          */
-        public loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fullName?: string): Promise<AssetContainer> {
-            return Promise.resolve().then(() => {
-                const loaderData = this._parse(data);
+        public loadAssetContainerAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<AssetContainer> {
+            return this._parseAsync(scene, data, rootUrl, fileName).then(loaderData => {
+                this._log(`Loading ${fileName || ""}`);
                 this._loader = this._getLoader(loaderData);
-                return this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress, fullName).then(result => {
+                return this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress, fileName).then(result => {
                     const container = new AssetContainer(scene);
                     Array.prototype.push.apply(container.meshes, result.meshes);
                     Array.prototype.push.apply(container.particleSystems, result.particleSystems);
@@ -520,29 +518,76 @@ module BABYLON {
             return new GLTFFileLoader();
         }
 
-        private _parse(data: string | ArrayBuffer): IGLTFLoaderData {
-            this._startPerformanceCounter("Parse");
+        /**
+         * The loader state or null if the loader is not active.
+         */
+        public get loaderState(): Nullable<GLTFLoaderState> {
+            return this._loader ? this._loader.state : null;
+        }
+
+        /**
+         * Returns a promise that resolves when the asset is completely loaded.
+         * @returns a promise that resolves when the asset is completely loaded.
+         */
+        public whenCompleteAsync(): Promise<void> {
+            return new Promise((resolve, reject) => {
+                this.onCompleteObservable.addOnce(() => {
+                    resolve();
+                });
+                this.onErrorObservable.addOnce(reason => {
+                    reject(reason);
+                });
+            });
+        }
+
+        private _parseAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, fileName?: string): Promise<IGLTFLoaderData> {
+            return Promise.resolve().then(() => {
+                const unpacked = (data instanceof ArrayBuffer) ? this._unpackBinary(data) : { json: data, bin: null };
+
+                return this._validateAsync(scene, unpacked.json, rootUrl, fileName).then(() => {
+                    this._startPerformanceCounter("Parse JSON");
+                    this._log(`JSON length: ${unpacked.json.length}`);
+
+                    const loaderData: IGLTFLoaderData = {
+                        json: JSON.parse(unpacked.json),
+                        bin: unpacked.bin
+                    };
+
+                    this._endPerformanceCounter("Parse JSON");
 
-            let parsedData: IGLTFLoaderData;
-            if (data instanceof ArrayBuffer) {
-                this._log(`Parsing binary`);
-                parsedData = this._parseBinary(data);
+                    this.onParsedObservable.notifyObservers(loaderData);
+                    this.onParsedObservable.clear();
+
+                    return loaderData;
+                });
+            });
+        }
+
+        private _validateAsync(scene: Scene, json: string, rootUrl: string, fileName?: string): Promise<void> {
+            if (!this.validate || typeof GLTFValidator === "undefined") {
+                return Promise.resolve();
             }
-            else {
-                this._log(`Parsing JSON`);
-                this._log(`JSON length: ${data.length}`);
 
-                parsedData = {
-                    json: JSON.parse(data),
-                    bin: null
-                };
+            this._startPerformanceCounter("Validate JSON");
+
+            const options: IGLTFValidationOptions = {
+                externalResourceFunction: uri => {
+                    return this.preprocessUrlAsync(rootUrl + uri)
+                        .then(url => scene._loadFileAsync(url, true, true))
+                        .then(data => new Uint8Array(data as ArrayBuffer));
+                }
+            };
+
+            if (fileName && fileName.substr(0, 5) !== "data:") {
+                options.uri = (rootUrl === "file:" ? fileName : `${rootUrl}${fileName}`);
             }
 
-            this.onParsedObservable.notifyObservers(parsedData);
-            this.onParsedObservable.clear();
+            return GLTFValidator.validateString(json, options).then(result => {
+                this._endPerformanceCounter("Validate JSON");
 
-            this._endPerformanceCounter("Parse");
-            return parsedData;
+                this.onValidatedObservable.notifyObservers(result);
+                this.onValidatedObservable.clear();
+            });
         }
 
         private _getLoader(loaderData: IGLTFLoaderData): IGLTFLoader {
@@ -581,13 +626,14 @@ module BABYLON {
             return createLoader(this);
         }
 
-        private _parseBinary(data: ArrayBuffer): IGLTFLoaderData {
+        private _unpackBinary(data: ArrayBuffer): { json: string, bin: Nullable<ArrayBufferView> } {
+            this._startPerformanceCounter("Unpack binary");
+            this._log(`Binary length: ${data.byteLength}`);
+
             const Binary = {
                 Magic: 0x46546C67
             };
 
-            this._log(`Binary length: ${data.byteLength}`);
-
             const binaryReader = new BinaryReader(data);
 
             const magic = binaryReader.readUint32();
@@ -601,15 +647,26 @@ module BABYLON {
                 this._log(`Binary version: ${version}`);
             }
 
+            let unpacked: { json: string, bin: Nullable<ArrayBufferView> };
             switch (version) {
-                case 1: return this._parseV1(binaryReader);
-                case 2: return this._parseV2(binaryReader);
+                case 1: {
+                    unpacked = this._unpackBinaryV1(binaryReader);
+                    break;
+                }
+                case 2: {
+                    unpacked = this._unpackBinaryV2(binaryReader);
+                    break;
+                }
+                default: {
+                    throw new Error("Unsupported version: " + version);
+                }
             }
 
-            throw new Error("Unsupported version: " + version);
+            this._endPerformanceCounter("Unpack binary");
+            return unpacked;
         }
 
-        private _parseV1(binaryReader: BinaryReader): IGLTFLoaderData {
+        private _unpackBinaryV1(binaryReader: BinaryReader): { json: string, bin: Nullable<ArrayBufferView> } {
             const ContentFormat = {
                 JSON: 0
             };
@@ -622,10 +679,10 @@ module BABYLON {
             const contentLength = binaryReader.readUint32();
             const contentFormat = binaryReader.readUint32();
 
-            let content: Object;
+            let content: string;
             switch (contentFormat) {
                 case ContentFormat.JSON: {
-                    content = JSON.parse(GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(contentLength)));
+                    content = GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(contentLength));
                     break;
                 }
                 default: {
@@ -642,7 +699,7 @@ module BABYLON {
             };
         }
 
-        private _parseV2(binaryReader: BinaryReader): IGLTFLoaderData {
+        private _unpackBinaryV2(binaryReader: BinaryReader): { json: string, bin: Nullable<ArrayBufferView> } {
             const ChunkFormat = {
                 JSON: 0x4E4F534A,
                 BIN: 0x004E4942
@@ -659,7 +716,7 @@ module BABYLON {
             if (chunkFormat !== ChunkFormat.JSON) {
                 throw new Error("First chunk format is not JSON");
             }
-            const json = JSON.parse(GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(chunkLength)));
+            const json = GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(chunkLength));
 
             // Look for BIN chunk
             let bin: Nullable<Uint8Array> = null;
@@ -707,7 +764,7 @@ module BABYLON {
             };
         }
 
-        private static _compareVersion(a: { major: number, minor: number }, b: { major: number, minor: number }) {
+        private static _compareVersion(a: { major: number, minor: number }, b: { major: number, minor: number }): number {
             if (a.major > b.major) return 1;
             if (a.major < b.major) return -1;
             if (a.minor > b.minor) return 1;

+ 1 - 0
localDev/index.html

@@ -8,6 +8,7 @@
     <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
     <script src="../dist/preview%20release/cannon.js"></script>
     <script src="../dist/preview%20release/Oimo.js"></script>
+    <script src="../dist/preview%20release/gltf_validator.js"></script>
     <script src="../Tools/DevLoader/BabylonLoader.js"></script>
     <script src="src/webgl-debug.js"></script>
 

+ 1 - 0
sandbox/index-local.html

@@ -6,6 +6,7 @@
     <link href="index.css" rel="stylesheet" />
     <script src="../dist/preview%20release/cannon.js"></script>
     <script src="../dist/preview%20release/Oimo.js"></script>
+    <script src="../dist/preview%20release/gltf_validator.js"></script>
     <script src="../Tools/DevLoader/BabylonLoader.js"></script>
 </head>
 <body>

+ 2 - 1
sandbox/index.html

@@ -32,8 +32,9 @@
 
     <script src="https://preview.babylonjs.com/cannon.js"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
+    <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
     <script src="https://preview.babylonjs.com/babylon.js"></script>
-    <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
+    <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script> 
 
     <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
     <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>

+ 22 - 1
sandbox/index.js

@@ -71,10 +71,23 @@ if (BABYLON.Engine.isSupported()) {
     // This is really important to tell Babylon.js to use decomposeLerp and matrix interpolation
     BABYLON.Animation.AllowMatricesInterpolation = true;
 
+    // Update the defaults of the GLTFTab in the inspector.
+    INSPECTOR.GLTFTab._GetLoaderDefaultsAsync().then(function (defaults) {
+        defaults.validate = true;
+    });
+
     // Setting up some GLTF values
     BABYLON.GLTFFileLoader.IncrementalLoading = false;
     BABYLON.SceneLoader.OnPluginActivatedObservable.add(function (plugin) {
         currentPluginName = plugin.name;
+        if (currentPluginName === "gltf") {
+            plugin.onValidatedObservable.add(function (results) {
+                if (results.issues.numErrors > 0) {
+                    debugLayerEnabled = true;
+                    debugLayerLastActiveTab = "GLTF";
+                }
+            });
+        }
     });
 
     // Resize
@@ -241,7 +254,15 @@ if (BABYLON.Engine.isSupported()) {
         loadFromAssetUrl();
     }
     else {
-        filesInput = new BABYLON.FilesInput(engine, null, sceneLoaded, null, null, null, function () { BABYLON.Tools.ClearLogCache() }, null, sceneError);
+        var startProcessingFiles = function () {
+            BABYLON.Tools.ClearLogCache();
+
+            if (currentScene) {
+                debugLayerLastActiveTab = currentScene.debugLayer.getActiveTab();
+            }
+        };
+
+        filesInput = new BABYLON.FilesInput(engine, null, sceneLoaded, null, null, null, startProcessingFiles, null, sceneError);
         filesInput.onProcessFileCallback = (function (file, name, extension) {
             if (filesInput._filesToLoad && filesInput._filesToLoad.length === 1 && extension) {
                 if (extension.toLowerCase() === "dds" || extension.toLowerCase() === "env") {

+ 5 - 0
src/Culling/babylon.boundingBox.ts

@@ -15,6 +15,11 @@
         private _worldMatrix: Matrix;
 
         /**
+         * @hidden
+         */
+        public _tag: number;
+
+        /**
          * Creates a new bounding box
          * @param min defines the minimum vector (in local space)
          * @param max defines the maximum vector (in local space)

+ 2 - 2
src/Debug/babylon.debugLayer.ts

@@ -52,7 +52,7 @@ module BABYLON {
         /** Creates the inspector window. */
         private _createInspector(config: {
             popup?: boolean,
-            initialTab?: number,
+            initialTab?: number | string,
             parentElement?: HTMLElement,
             newColors?: {
                 backgroundColor?: string,
@@ -117,7 +117,7 @@ module BABYLON {
 
         public show(config: {
             popup?: boolean,
-            initialTab?: number,
+            initialTab?: number | string,
             parentElement?: HTMLElement,
             newColors?: {
                 backgroundColor?: string,

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 149 - 151
src/Loading/babylon.sceneLoader.ts


+ 11 - 8
src/Mesh/babylon.mesh.ts

@@ -3130,12 +3130,14 @@
          * Creates a ground mesh from a height map.    
          * tuto : http://doc.babylonjs.com/babylon101/height_map   
          * Please consider using the same method from the MeshBuilder class instead.    
-         * The parameter `url` sets the URL of the height map image resource.  
-         * The parameters `width` and `height` (positive floats, default 10) set the ground width and height sizes.     
-         * The parameter `subdivisions` (positive integer, default 1) sets the number of subdivision per side.  
-         * The parameter `minHeight` (float, default 0) is the minimum altitude on the ground.     
-         * The parameter `maxHeight` (float, default 1) is the maximum altitude on the ground.   
-         * The parameter `onReady` is a javascript callback function that will be called  once the mesh is just built (the height map download can last some time).  
+         * @param url sets the URL of the height map image resource.  
+         * @param width (positive float, default 10) set the ground width size.  
+         * @param height (positive float, default 10) set the ground height size.  
+         * @param subdivisions (positive integer, default 1) sets the number of subdivision per side.  
+         * @param minHeight (float, default 0) is the minimum altitude on the ground.     
+         * @param maxHeight (float, default 1) is the maximum altitude on the ground.   
+         * @param onReady is a javascript callback function that will be called  once the mesh is just built (the height map download can last some time).  
+         * @param alphaFilter will filter any data where the alpha channel is below this value, defaults 0 (all data visible).
          * This function is passed the newly built mesh : 
          * ```javascript
          * function(mesh) { // do things
@@ -3143,7 +3145,7 @@
          * ```
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateGroundFromHeightMap(name: string, url: string, width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, scene: Scene, updatable?: boolean, onReady?: (mesh: GroundMesh) => void): GroundMesh {
+        public static CreateGroundFromHeightMap(name: string, url: string, width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, scene: Scene, updatable?: boolean, onReady?: (mesh: GroundMesh) => void, alphaFilter?: number): GroundMesh {
             var options = {
                 width: width,
                 height: height,
@@ -3151,7 +3153,8 @@
                 minHeight: minHeight,
                 maxHeight: maxHeight,
                 updatable: updatable,
-                onReady: onReady
+                onReady: onReady,
+                alphaFilter: alphaFilter
             };
 
             return MeshBuilder.CreateGroundFromHeightMap(name, url, options, scene);

+ 35 - 9
src/Mesh/babylon.mesh.vertexData.ts

@@ -1739,15 +1739,17 @@
           * * buffer the array holding the image color data 
           * * bufferWidth the width of image
           * * bufferHeight the height of image
+          * * alphaFilter Remove any data where the alpha channel is below this value, defaults 0 (all data visible)
          * @returns the VertexData of the Ground designed from a heightmap   
          */
-        public static CreateGroundFromHeightMap(options: { width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, colorFilter: Color3, buffer: Uint8Array, bufferWidth: number, bufferHeight: number }): VertexData {
+        public static CreateGroundFromHeightMap(options: { width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, colorFilter: Color3, buffer: Uint8Array, bufferWidth: number, bufferHeight: number, alphaFilter: number }): VertexData {
             var indices = [];
             var positions = [];
             var normals = [];
             var uvs = [];
             var row, col;
             var filter = options.colorFilter || new Color3(0.3, 0.59, 0.11);
+            var alphaFilter = options.alphaFilter || 0.0;
 
             // Vertices
             for (row = 0; row <= options.subdivisions; row++) {
@@ -1762,10 +1764,17 @@
                     var r = options.buffer[pos] / 255.0;
                     var g = options.buffer[pos + 1] / 255.0;
                     var b = options.buffer[pos + 2] / 255.0;
+                    var a = options.buffer[pos + 3] / 255.0;
 
                     var gradient = r * filter.r + g * filter.g + b * filter.b;
-
-                    position.y = options.minHeight + (options.maxHeight - options.minHeight) * gradient;
+                    
+                    // If our alpha channel is not within our filter then we will assign a 'special' height 
+                    // Then when building the indices, we will ignore any vertex that is using the special height
+                    if(a >= alphaFilter)
+                        position.y = options.minHeight + (options.maxHeight - options.minHeight) * gradient;
+                    else {
+                        position.y = options.minHeight - BABYLON.Epsilon; // We can't have a height below minHeight, normally.
+                    }
 
                     // Add  vertex
                     positions.push(position.x, position.y, position.z);
@@ -1777,13 +1786,30 @@
             // Indices
             for (row = 0; row < options.subdivisions; row++) {
                 for (col = 0; col < options.subdivisions; col++) {
-                    indices.push(col + 1 + (row + 1) * (options.subdivisions + 1));
-                    indices.push(col + 1 + row * (options.subdivisions + 1));
-                    indices.push(col + row * (options.subdivisions + 1));
+                    // Calculate Indices
+                    var idx1 = (col + 1 + (row + 1) * (options.subdivisions + 1));
+                    var idx2 = (col + 1 + row * (options.subdivisions + 1));
+                    var idx3 = (col + row * (options.subdivisions + 1));
+                    var idx4 = (col + (row + 1) * (options.subdivisions + 1));
+
+                    // Check that all indices are visible (based on our special height)
+                    // Only display the vertex if all Indices are visible
+                    // Positions are stored x,y,z for each vertex, hence the * 3 and + 1 for height
+                    var isVisibleIdx1 = positions[idx1 * 3 + 1] >= options.minHeight;
+                    var isVisibleIdx2 = positions[idx2 * 3 + 1] >= options.minHeight;
+                    var isVisibleIdx3 = positions[idx3 * 3 + 1] >= options.minHeight;
+                    if (isVisibleIdx1 && isVisibleIdx2 && isVisibleIdx3) {
+                        indices.push(idx1);
+                        indices.push(idx2);
+                        indices.push(idx3);
+                    }
 
-                    indices.push(col + (row + 1) * (options.subdivisions + 1));
-                    indices.push(col + 1 + (row + 1) * (options.subdivisions + 1));
-                    indices.push(col + row * (options.subdivisions + 1));
+                    var isVisibleIdx4 = positions[idx4 * 3 + 1] >= options.minHeight;
+                    if (isVisibleIdx4 && isVisibleIdx1 && isVisibleIdx3) {
+                        indices.push(idx4);
+                        indices.push(idx1);
+                        indices.push(idx3);
+                    }
                 }
             }
 

+ 5 - 2
src/Mesh/babylon.meshBuilder.ts

@@ -776,6 +776,7 @@
          * * The parameter `maxHeight` (float, default 1) is the maximum altitude on the ground.   
          * * The parameter `colorFilter` (optional Color3, default (0.3, 0.59, 0.11) ) is the filter to apply to the image pixel colors to compute the height.  
          * * The parameter `onReady` is a javascript callback function that will be called  once the mesh is just built (the height map download can last some time).  
+         * * The parameter `alphaFilter` will filter any data where the alpha channel is below this value, defaults 0 (all data visible)
          * * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          * @param name defines the name of the mesh
          * @param url defines the url to the height map
@@ -785,13 +786,14 @@
          * @see http://doc.babylonjs.com/babylon101/height_map   
          * @see http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#ground-from-a-height-map
          */
-        public static CreateGroundFromHeightMap(name: string, url: string, options: { width?: number, height?: number, subdivisions?: number, minHeight?: number, maxHeight?: number, colorFilter?: Color3, updatable?: boolean, onReady?: (mesh: GroundMesh) => void }, scene: Scene): GroundMesh {
+        public static CreateGroundFromHeightMap(name: string, url: string, options: { width?: number, height?: number, subdivisions?: number, minHeight?: number, maxHeight?: number, colorFilter?: Color3, alphaFilter?: number, updatable?: boolean, onReady?: (mesh: GroundMesh) => void }, scene: Scene): GroundMesh {
             var width = options.width || 10.0;
             var height = options.height || 10.0;
             var subdivisions = options.subdivisions || 1 | 0;
             var minHeight = options.minHeight || 0.0;
             var maxHeight = options.maxHeight || 1.0;
             var filter = options.colorFilter || new Color3(0.3, 0.59, 0.11);
+            var alphaFilter = options.alphaFilter || 0.0;
             var updatable = options.updatable;
             var onReady = options.onReady;
 
@@ -834,7 +836,8 @@
                     width: width, height: height,
                     subdivisions: subdivisions,
                     minHeight: minHeight, maxHeight: maxHeight, colorFilter: filter,
-                    buffer: buffer, bufferWidth: bufferWidth, bufferHeight: bufferHeight
+                    buffer: buffer, bufferWidth: bufferWidth, bufferHeight: bufferHeight, 
+                    alphaFilter: alphaFilter
                 });
 
                 vertexData.applyToMesh(ground, updatable);

+ 158 - 0
src/Physics/babylon.IPhysicsEngine.ts

@@ -0,0 +1,158 @@
+module BABYLON {
+    /**
+     * Interface used to describe a physics joint
+     */
+    export interface PhysicsImpostorJoint {
+        /** Defines the main impostor to which the joint is linked */
+        mainImpostor: PhysicsImpostor;
+        /** Defines the impostor that is connected to the main impostor using this joint */
+        connectedImpostor: PhysicsImpostor;
+        /** Defines the joint itself */
+        joint: PhysicsJoint;
+    }
+
+    /** @hidden */
+    export interface IPhysicsEnginePlugin {
+        world: any;
+        name: string;
+        setGravity(gravity: Vector3): void;
+        setTimeStep(timeStep: number): void;
+        getTimeStep(): number;
+        executeStep(delta: number, impostors: Array<PhysicsImpostor>): void; //not forgetting pre and post events
+        applyImpulse(impostor: PhysicsImpostor, force: Vector3, contactPoint: Vector3): void;
+        applyForce(impostor: PhysicsImpostor, force: Vector3, contactPoint: Vector3): void;
+        generatePhysicsBody(impostor: PhysicsImpostor): void;
+        removePhysicsBody(impostor: PhysicsImpostor): void;
+        generateJoint(joint: PhysicsImpostorJoint): void;
+        removeJoint(joint: PhysicsImpostorJoint): void;
+        isSupported(): boolean;
+        setTransformationFromPhysicsBody(impostor: PhysicsImpostor): void;
+        setPhysicsBodyTransformation(impostor: PhysicsImpostor, newPosition: Vector3, newRotation: Quaternion): void;
+        setLinearVelocity(impostor: PhysicsImpostor, velocity: Nullable<Vector3>): void;
+        setAngularVelocity(impostor: PhysicsImpostor, velocity: Nullable<Vector3>): void;
+        getLinearVelocity(impostor: PhysicsImpostor): Nullable<Vector3>;
+        getAngularVelocity(impostor: PhysicsImpostor): Nullable<Vector3>;
+        setBodyMass(impostor: PhysicsImpostor, mass: number): void;
+        getBodyMass(impostor: PhysicsImpostor): number;
+        getBodyFriction(impostor: PhysicsImpostor): number;
+        setBodyFriction(impostor: PhysicsImpostor, friction: number): void;
+        getBodyRestitution(impostor: PhysicsImpostor): number;
+        setBodyRestitution(impostor: PhysicsImpostor, restitution: number): void;
+        sleepBody(impostor: PhysicsImpostor): void;
+        wakeUpBody(impostor: PhysicsImpostor): void;
+        //Joint Update
+        updateDistanceJoint(joint: PhysicsJoint, maxDistance: number, minDistance?: number): void;
+        setMotor(joint: IMotorEnabledJoint, speed: number, maxForce?: number, motorIndex?: number): void;
+        setLimit(joint: IMotorEnabledJoint, upperLimit: number, lowerLimit?: number, motorIndex?: number): void;
+        getRadius(impostor: PhysicsImpostor): number;
+        getBoxSizeToRef(impostor: PhysicsImpostor, result: Vector3): void;
+        syncMeshWithImpostor(mesh: AbstractMesh, impostor: PhysicsImpostor): void;
+        dispose(): void;
+    }
+
+    /**
+     * Interface used to define a physics engine
+     * @see http://doc.babylonjs.com/how_to/using_the_physics_engine
+     */
+    export interface IPhysicsEngine {
+        /**
+         * Gets the gravity vector used by the simulation
+         */
+        gravity: Vector3;
+
+        /**
+         * Sets the gravity vector used by the simulation
+         * @param gravity defines the gravity vector to use
+         */
+        setGravity(gravity: Vector3): void;
+
+        /**
+         * Set the time step of the physics engine.
+         * Default is 1/60.
+         * To slow it down, enter 1/600 for example.
+         * To speed it up, 1/30
+         * @param newTimeStep the new timestep to apply to this world.
+         */
+        setTimeStep(newTimeStep: number): void;
+
+        /**
+         * Get the time step of the physics engine.
+         * @returns the current time step
+         */
+        getTimeStep(): number;
+
+        /**
+         * Release all resources
+         */
+        dispose(): void;
+
+        /**
+         * Gets the name of the current physics plugin
+         * @returns the name of the plugin
+         */
+        getPhysicsPluginName(): string;
+
+        /**
+         * Adding a new impostor for the impostor tracking.
+         * This will be done by the impostor itself.
+         * @param impostor the impostor to add
+         */
+        addImpostor(impostor: PhysicsImpostor): void;
+
+        /**
+         * Remove an impostor from the engine.
+         * This impostor and its mesh will not longer be updated by the physics engine.
+         * @param impostor the impostor to remove
+         */
+        removeImpostor(impostor: PhysicsImpostor): void;
+
+        /**
+         * Add a joint to the physics engine
+         * @param mainImpostor defines the main impostor to which the joint is added.
+         * @param connectedImpostor defines the impostor that is connected to the main impostor using this joint
+         * @param joint defines the joint that will connect both impostors.
+         */
+        addJoint(mainImpostor: PhysicsImpostor, connectedImpostor: PhysicsImpostor, joint: PhysicsJoint): void;
+
+        /**
+         * Removes a joint from the simulation
+         * @param mainImpostor defines the impostor used with the joint
+         * @param connectedImpostor defines the other impostor connected to the main one by the joint
+         * @param joint defines the joint to remove
+         */
+        removeJoint(mainImpostor: PhysicsImpostor, connectedImpostor: PhysicsImpostor, joint: PhysicsJoint): void;
+
+        /**
+         * Gets the current plugin used to run the simulation
+         * @returns current plugin
+         */
+        getPhysicsPlugin(): IPhysicsEnginePlugin;
+
+        /**
+         * Gets the list of physic impostors
+         * @returns an array of PhysicsImpostor
+         */
+        getImpostors(): Array<PhysicsImpostor>;
+
+        /**
+         * Gets the impostor for a physics enabled object
+         * @param object defines the object impersonated by the impostor
+         * @returns the PhysicsImpostor or null if not found
+         */
+        getImpostorForPhysicsObject(object: IPhysicsEnabledObject): Nullable<PhysicsImpostor>;
+
+        /**
+         * Gets the impostor for a physics body object
+         * @param body defines physics body used by the impostor
+         * @returns the PhysicsImpostor or null if not found
+         */        
+        getImpostorWithPhysicsBody(body: any): Nullable<PhysicsImpostor>;
+
+        /**
+         * Called by the scene. No need to call it.
+         * @param delta defines the timespam between frames
+         */
+        step(delta: number): void;
+    }
+
+}

+ 66 - 65
src/Physics/babylon.physicsEngine.ts

@@ -1,15 +1,28 @@
 module BABYLON {
+    
+    /**
+     * Class used to control physics engine
+     * @see http://doc.babylonjs.com/how_to/using_the_physics_engine
+     */
+    export class PhysicsEngine implements IPhysicsEngine {
+        /**
+         * Global value used to control the smallest number supported by the simulation
+         */
+        public static Epsilon = 0.001;
 
-    export interface PhysicsImpostorJoint {
-        mainImpostor: PhysicsImpostor;
-        connectedImpostor: PhysicsImpostor;
-        joint: PhysicsJoint;
-    }
-
-    export class PhysicsEngine {
+        private _impostors: Array<PhysicsImpostor> = [];
+        private _joints: Array<PhysicsImpostorJoint> = [];
 
+        /**
+         * Gets the gravity vector used by the simulation
+         */
         public gravity: Vector3;
 
+        /**
+         * Creates a new Physics Engine
+         * @param gravity defines the gravity vector used by the simulation
+         * @param _physicsPlugin defines the plugin to use (CannonJS by default)
+         */
         constructor(gravity: Nullable<Vector3>, private _physicsPlugin: IPhysicsEnginePlugin = new CannonJSPlugin()) {
             if (!this._physicsPlugin.isSupported()) {
                 throw new Error("Physics Engine " + this._physicsPlugin.name + " cannot be found. "
@@ -20,6 +33,10 @@
             this.setTimeStep();
         }
 
+        /**
+         * Sets the gravity vector used by the simulation
+         * @param gravity defines the gravity vector to use
+         */
         public setGravity(gravity: Vector3): void {
             this.gravity = gravity;
             this._physicsPlugin.setGravity(this.gravity);
@@ -27,10 +44,10 @@
 
         /**
          * Set the time step of the physics engine.
-         * default is 1/60.
+         * Default is 1/60.
          * To slow it down, enter 1/600 for example.
          * To speed it up, 1/30
-         * @param {number} newTimeStep the new timestep to apply to this world.
+         * @param newTimeStep defines the new timestep to apply to this world.
          */
         public setTimeStep(newTimeStep: number = 1 / 60) {
             this._physicsPlugin.setTimeStep(newTimeStep);
@@ -38,11 +55,15 @@
 
         /**
          * Get the time step of the physics engine.
+         * @returns the current time step
          */
         public getTimeStep(): number {
             return this._physicsPlugin.getTimeStep();
         }
 
+        /**
+         * Release all resources
+         */
         public dispose(): void {
             this._impostors.forEach(function (impostor) {
                 impostor.dispose();
@@ -50,22 +71,18 @@
             this._physicsPlugin.dispose();
         }
 
+        /**
+         * Gets the name of the current physics plugin
+         * @returns the name of the plugin
+         */        
         public getPhysicsPluginName(): string {
             return this._physicsPlugin.name;
         }
 
-        // Statics
-        public static Epsilon = 0.001;
-
-        //new methods and parameters
-
-        private _impostors: Array<PhysicsImpostor> = [];
-        private _joints: Array<PhysicsImpostorJoint> = [];
-
         /**
          * Adding a new impostor for the impostor tracking.
          * This will be done by the impostor itself.
-         * @param {PhysicsImpostor} impostor the impostor to add
+         * @param impostor the impostor to add
          */
         public addImpostor(impostor: PhysicsImpostor) {
             impostor.uniqueId = this._impostors.push(impostor);
@@ -78,7 +95,7 @@
         /**
          * Remove an impostor from the engine.
          * This impostor and its mesh will not longer be updated by the physics engine.
-         * @param {PhysicsImpostor} impostor the impostor to remove
+         * @param impostor the impostor to remove
          */
         public removeImpostor(impostor: PhysicsImpostor) {
             var index = this._impostors.indexOf(impostor);
@@ -94,9 +111,9 @@
 
         /**
          * Add a joint to the physics engine
-         * @param {PhysicsImpostor} mainImpostor the main impostor to which the joint is added.
-         * @param {PhysicsImpostor} connectedImpostor the impostor that is connected to the main impostor using this joint
-         * @param {PhysicsJoint} the joint that will connect both impostors.
+         * @param mainImpostor defines the main impostor to which the joint is added.
+         * @param connectedImpostor defines the impostor that is connected to the main impostor using this joint
+         * @param joint defines the joint that will connect both impostors.
          */
         public addJoint(mainImpostor: PhysicsImpostor, connectedImpostor: PhysicsImpostor, joint: PhysicsJoint) {
             var impostorJoint = {
@@ -109,6 +126,12 @@
             this._physicsPlugin.generateJoint(impostorJoint);
         }
 
+        /**
+         * Removes a joint from the simulation
+         * @param mainImpostor defines the impostor used with the joint
+         * @param connectedImpostor defines the other impostor connected to the main one by the joint
+         * @param joint defines the joint to remove
+         */
         public removeJoint(mainImpostor: PhysicsImpostor, connectedImpostor: PhysicsImpostor, joint: PhysicsJoint) {
             var matchingJoints = this._joints.filter(function (impostorJoint) {
                 return (impostorJoint.connectedImpostor === connectedImpostor
@@ -123,10 +146,10 @@
         }
 
         /**
-         * Called by the scene. no need to call it.
-         * @hidden
+         * Called by the scene. No need to call it.
+         * @param delta defines the timespam between frames
          */
-        public _step(delta: number) {
+        public step(delta: number) {
             //check if any mesh has no body / requires an update
             this._impostors.forEach((impostor) => {
 
@@ -144,14 +167,27 @@
             this._physicsPlugin.executeStep(delta, this._impostors);
         }
 
+        /**
+         * Gets the current plugin used to run the simulation
+         * @returns current plugin
+         */
         public getPhysicsPlugin(): IPhysicsEnginePlugin {
             return this._physicsPlugin;
         }
 
+        /**
+         * Gets the list of physic impostors
+         * @returns an array of PhysicsImpostor
+         */
         public getImpostors(): Array<PhysicsImpostor> {
             return this._impostors;
         }
 
+        /**
+         * Gets the impostor for a physics enabled object
+         * @param object defines the object impersonated by the impostor
+         * @returns the PhysicsImpostor or null if not found
+         */
         public getImpostorForPhysicsObject(object: IPhysicsEnabledObject): Nullable<PhysicsImpostor> {
             for (var i = 0; i < this._impostors.length; ++i) {
                 if (this._impostors[i].object === object) {
@@ -162,6 +198,11 @@
             return null;
         }
 
+        /**
+         * Gets the impostor for a physics body object
+         * @param body defines physics body used by the impostor
+         * @returns the PhysicsImpostor or null if not found
+         */        
         public getImpostorWithPhysicsBody(body: any): Nullable<PhysicsImpostor> {
             for (var i = 0; i < this._impostors.length; ++i) {
                 if (this._impostors[i].physicsBody === body) {
@@ -171,45 +212,5 @@
 
             return null;
         }
-
-    }
-
-    export interface IPhysicsEnginePlugin {
-        world: any;
-        name: string;
-        setGravity(gravity: Vector3): void;
-        setTimeStep(timeStep: number): void;
-        getTimeStep(): number;
-        executeStep(delta: number, impostors: Array<PhysicsImpostor>): void; //not forgetting pre and post events
-        applyImpulse(impostor: PhysicsImpostor, force: Vector3, contactPoint: Vector3): void;
-        applyForce(impostor: PhysicsImpostor, force: Vector3, contactPoint: Vector3): void;
-        generatePhysicsBody(impostor: PhysicsImpostor): void;
-        removePhysicsBody(impostor: PhysicsImpostor): void;
-        generateJoint(joint: PhysicsImpostorJoint): void;
-        removeJoint(joint: PhysicsImpostorJoint): void;
-        isSupported(): boolean;
-        setTransformationFromPhysicsBody(impostor: PhysicsImpostor): void;
-        setPhysicsBodyTransformation(impostor: PhysicsImpostor, newPosition: Vector3, newRotation: Quaternion): void;
-        setLinearVelocity(impostor: PhysicsImpostor, velocity: Nullable<Vector3>): void;
-        setAngularVelocity(impostor: PhysicsImpostor, velocity: Nullable<Vector3>): void;
-        getLinearVelocity(impostor: PhysicsImpostor): Nullable<Vector3>;
-        getAngularVelocity(impostor: PhysicsImpostor): Nullable<Vector3>;
-        setBodyMass(impostor: PhysicsImpostor, mass: number): void;
-        getBodyMass(impostor: PhysicsImpostor): number;
-        getBodyFriction(impostor: PhysicsImpostor): number;
-        setBodyFriction(impostor: PhysicsImpostor, friction: number): void;
-        getBodyRestitution(impostor: PhysicsImpostor): number;
-        setBodyRestitution(impostor: PhysicsImpostor, restitution: number): void;
-        sleepBody(impostor: PhysicsImpostor): void;
-        wakeUpBody(impostor: PhysicsImpostor): void;
-        //Joint Update
-        updateDistanceJoint(joint: PhysicsJoint, maxDistance: number, minDistance?: number): void;
-        setMotor(joint: IMotorEnabledJoint, speed: number, maxForce?: number, motorIndex?: number): void;
-        setLimit(joint: IMotorEnabledJoint, upperLimit: number, lowerLimit?: number, motorIndex?: number): void;
-        getRadius(impostor: PhysicsImpostor): number;
-        getBoxSizeToRef(impostor: PhysicsImpostor, result: Vector3): void;
-        syncMeshWithImpostor(mesh: AbstractMesh, impostor: PhysicsImpostor): void;
-        dispose(): void;
     }
-
 }

+ 98 - 0
src/Physics/babylon.physicsEngineComponent.ts

@@ -0,0 +1,98 @@
+module BABYLON {
+    export interface Scene {
+        /** @hidden (Backing field) */        
+        _physicsEngine: Nullable<IPhysicsEngine>;
+
+        /**
+         * Gets the current physics engine
+         * @returns a IPhysicsEngine or null if none attached
+         */
+        getPhysicsEngine(): Nullable<IPhysicsEngine>;
+
+        /**
+         * Enables physics to the current scene
+         * @param gravity defines the scene's gravity for the physics engine
+         * @param plugin defines the physics engine to be used. defaults to OimoJS.
+         * @return a boolean indicating if the physics engine was initialized
+         */
+        enablePhysics(gravity: Nullable<Vector3>, plugin?: IPhysicsEnginePlugin): boolean;
+
+        /** 
+         * Disables and disposes the physics engine associated with the scene
+         */
+        disablePhysicsEngine(): void;
+
+        /**
+         * Gets a boolean indicating if there is an active physics engine
+         * @returns a boolean indicating if there is an active physics engine
+         */
+        isPhysicsEnabled(): boolean;   
+
+        /**
+         * Deletes a physics compound impostor
+         * @param compound defines the compound to delete
+         */
+        deleteCompoundImpostor(compound: any): void;
+    }
+
+    /** 
+     * Gets the current physics engine
+     * @returns a IPhysicsEngine or null if none attached
+     */
+    Scene.prototype.getPhysicsEngine = function(): Nullable<IPhysicsEngine> {
+        return this._physicsEngine;
+    }
+
+    /**
+     * Enables physics to the current scene
+     * @param gravity defines the scene's gravity for the physics engine
+     * @param plugin defines the physics engine to be used. defaults to OimoJS.
+     * @return a boolean indicating if the physics engine was initialized
+     */
+    Scene.prototype.enablePhysics = function(gravity: Nullable<Vector3> = null, plugin?: IPhysicsEnginePlugin): boolean {
+        if (this._physicsEngine) {
+            return true;
+        }
+
+        try {
+            this._physicsEngine = new PhysicsEngine(gravity, plugin);
+            return true;
+        } catch (e) {
+            Tools.Error(e.message);
+            return false;
+        }
+    }
+
+    /** 
+     * Disables and disposes the physics engine associated with the scene
+     */
+    Scene.prototype.disablePhysicsEngine = function(): void {
+        if (!this._physicsEngine) {
+            return;
+        }
+
+        this._physicsEngine.dispose();
+        this._physicsEngine = null;
+    }
+
+    /**
+     * Gets a boolean indicating if there is an active physics engine
+     * @returns a boolean indicating if there is an active physics engine
+     */
+    Scene.prototype.isPhysicsEnabled = function(): boolean {
+        return this._physicsEngine !== undefined;
+    }
+
+    /**
+     * Deletes a physics compound impostor
+     * @param compound defines the compound to delete
+     */
+    Scene.prototype.deleteCompoundImpostor = function(compound: any): void {
+        var mesh: AbstractMesh = compound.parts[0].mesh;
+
+        if (mesh.physicsImpostor) {
+            mesh.physicsImpostor.dispose(/*true*/);
+            mesh.physicsImpostor = null;
+        }
+    }
+}

+ 1 - 1
src/Physics/babylon.physicsHelper.ts

@@ -3,7 +3,7 @@ module BABYLON {
     export class PhysicsHelper {
 
         private _scene: Scene;
-        private _physicsEngine: Nullable<PhysicsEngine>;
+        private _physicsEngine: Nullable<IPhysicsEngine>;
 
         constructor(scene: Scene) {
             this._scene = scene;

+ 1 - 1
src/Physics/babylon.physicsImpostor.ts

@@ -36,7 +36,7 @@ module BABYLON {
 
         public static IDENTITY_QUATERNION = Quaternion.Identity();
 
-        private _physicsEngine: Nullable<PhysicsEngine>;
+        private _physicsEngine: Nullable<IPhysicsEngine>;
         //The native cannon/oimo/energy physics body object.
         private _physicsBody: any;
         private _bodyUpdateRequired: boolean = false;

+ 12 - 4
src/Rendering/babylon.boundingBoxRenderer.ts

@@ -81,7 +81,7 @@
         public frontColor = new Color3(1, 1, 1);
         public backColor = new Color3(0.1, 0.1, 0.1);
         public showBackLines = true;
-        public renderList = new SmartArray<BoundingBox>(32);
+        public renderList = new SmartArray<BoundingBox>(32);        
 
         private _colorShader: ShaderMaterial;
         private _vertexBuffers: { [key: string]: Nullable<VertexBuffer> } = {};
@@ -102,13 +102,14 @@
 
             this.scene._evaluateSubMeshStage.registerStep(SceneComponentConstants.STEP_EVALUATESUBMESH_BOUNDINGBOXRENDERER, this, this._evaluateSubMesh);
 
-            this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_BOUNDINGBOXRENDERER, this, this.render);
+            this.scene._afterRenderingGroupDrawStage.registerStep(SceneComponentConstants.STEP_AFTERRENDERINGGROUPDRAW_BOUNDINGBOXRENDERER, this, this.render);
         }
 
         private _evaluateSubMesh(mesh: AbstractMesh, subMesh: SubMesh): void {
             if (mesh.showSubMeshesBoundingBox) {
                 const boundingInfo = subMesh.getBoundingInfo();
                 if (boundingInfo !== null && boundingInfo !== undefined) {
+                    boundingInfo.boundingBox._tag = mesh.renderingGroupId;
                     this.renderList.push(boundingInfo.boundingBox);
                 }
             }
@@ -117,7 +118,7 @@
         private _activeMesh(sourceMesh: AbstractMesh, mesh: AbstractMesh): void {
             if (sourceMesh.showBoundingBox || this.scene.forceShowBoundingBoxes) {
                 let boundingInfo = sourceMesh.getBoundingInfo();
-
+                boundingInfo.boundingBox._tag = mesh.renderingGroupId;
                 this.renderList.push(boundingInfo.boundingBox);
             }
         }
@@ -161,7 +162,11 @@
             this.renderList.reset();
         }
 
-        public render(): void {
+        /**
+         * Render the bounding boxes of a specific rendering group
+         * @param renderingGroupId defines the rendering group to render
+         */
+        public render(renderingGroupId: number): void {
             if (this.renderList.length === 0) {
                 return;
             }
@@ -177,6 +182,9 @@
             this._colorShader._preBind();
             for (var boundingBoxIndex = 0; boundingBoxIndex < this.renderList.length; boundingBoxIndex++) {
                 var boundingBox = this.renderList.data[boundingBoxIndex];
+                if (boundingBox._tag !== renderingGroupId) {
+                    continue;
+                }
                 var min = boundingBox.minimum;
                 var max = boundingBox.maximum;
                 var diff = max.subtract(min);

+ 3 - 4
src/Tools/babylon.filesInput.ts

@@ -129,9 +129,8 @@
                     && name.indexOf(".binary.babylon") === -1 && name.indexOf(".incremental.babylon") === -1) {
                     this._sceneFileToLoad = files[i];
                 }
-                else {
-                    FilesInput.FilesToLoad[name] = files[i];
-                }
+
+                FilesInput.FilesToLoad[name] = files[i];
             }
         }
 
@@ -225,7 +224,7 @@
                     this._engine.stopRenderLoop();
                 }
 
-                SceneLoader.LoadAsync("file:", this._sceneFileToLoad, this._engine, progress => {
+                SceneLoader.LoadAsync("file:", this._sceneFileToLoad.name, this._engine, progress => {
                     if (this._progressCallback) {
                         this._progressCallback(progress);
                     }

+ 3 - 65
src/babylon.scene.ts

@@ -963,7 +963,6 @@
         private _softwareSkinnedMeshes = new SmartArrayNoDuplicate<Mesh>(32);
 
         private _renderingManager: RenderingManager;
-        private _physicsEngine: Nullable<PhysicsEngine>;
 
         /** @hidden */
         public _activeAnimatables = new Array<Animatable>();
@@ -4437,7 +4436,7 @@
                     // Physics
                     if (this._physicsEngine) {
                         this.onBeforePhysicsObservable.notifyObservers(this);
-                        this._physicsEngine._step(defaultFrameTime / 1000);
+                        this._physicsEngine.step(defaultFrameTime / 1000);
                         this.onAfterPhysicsObservable.notifyObservers(this);
                     }
 
@@ -4462,7 +4461,7 @@
                 // Physics
                 if (this._physicsEngine) {
                     this.onBeforePhysicsObservable.notifyObservers(this);
-                    this._physicsEngine._step(deltaTime / 1000.0);
+                    this._physicsEngine.step(deltaTime / 1000.0);
                     this.onAfterPhysicsObservable.notifyObservers(this);
                 }
             }
@@ -5302,68 +5301,7 @@
 
         // Physics
 
-        /** 
-         * Gets the current physics engine
-         * @returns a PhysicsEngine or null if none attached
-         */
-        public getPhysicsEngine(): Nullable<PhysicsEngine> {
-            return this._physicsEngine;
-        }
-
-        /**
-         * Enables physics to the current scene
-         * @param gravity defines the scene's gravity for the physics engine
-         * @param plugin defines the physics engine to be used. defaults to OimoJS.
-         * @return a boolean indicating if the physics engine was initialized
-         */
-        public enablePhysics(gravity: Nullable<Vector3> = null, plugin?: IPhysicsEnginePlugin): boolean {
-            if (this._physicsEngine) {
-                return true;
-            }
-
-            try {
-                this._physicsEngine = new PhysicsEngine(gravity, plugin);
-                return true;
-            } catch (e) {
-                Tools.Error(e.message);
-                return false;
-            }
-
-        }
-
-        /** 
-         * Disables and disposes the physics engine associated with the scene
-         */
-        public disablePhysicsEngine(): void {
-            if (!this._physicsEngine) {
-                return;
-            }
-
-            this._physicsEngine.dispose();
-            this._physicsEngine = null;
-        }
-
-        /**
-         * Gets a boolean indicating if there is an active physics engine
-         * @returns a boolean indicating if there is an active physics engine
-         */
-        public isPhysicsEnabled(): boolean {
-            return this._physicsEngine !== undefined;
-        }
-
-        /**
-         * Deletes a physics compound impostor
-         * @param compound defines the compound to delete
-         */
-        public deleteCompoundImpostor(compound: any): void {
-            var mesh: AbstractMesh = compound.parts[0].mesh;
-
-            if (mesh.physicsImpostor) {
-                mesh.physicsImpostor.dispose(/*true*/);
-                mesh.physicsImpostor = null;
-            }
-        }
-
+      
         // Misc.
         /** @hidden */
         public _rebuildGeometries(): void {

+ 3 - 3
src/babylon.sceneComponent.ts

@@ -38,6 +38,7 @@
         public static readonly STEP_AFTERRENDERINGMESH_OUTLINE = 0;
 
         public static readonly STEP_AFTERRENDERINGGROUPDRAW_EFFECTLAYER_DRAW = 0;
+        public static readonly STEP_AFTERRENDERINGGROUPDRAW_BOUNDINGBOXRENDERER = 1;
 
         public static readonly STEP_BEFORECAMERAUPDATE_SIMPLIFICATIONQUEUE = 0;
         public static readonly STEP_BEFORECAMERAUPDATE_GAMEPAD = 1;
@@ -46,9 +47,8 @@
 
         public static readonly STEP_AFTERCAMERADRAW_EFFECTLAYER = 0;
         public static readonly STEP_AFTERCAMERADRAW_LENSFLARESYSTEM = 1;
-        public static readonly STEP_AFTERCAMERADRAW_BOUNDINGBOXRENDERER = 2;
-        public static readonly STEP_AFTERCAMERADRAW_EFFECTLAYER_DRAW = 3;
-        public static readonly STEP_AFTERCAMERADRAW_LAYER = 4;
+        public static readonly STEP_AFTERCAMERADRAW_EFFECTLAYER_DRAW = 2;
+        public static readonly STEP_AFTERCAMERADRAW_LAYER = 3;
 
         public static readonly STEP_GATHERRENDERTARGETS_SHADOWGENERATOR = 0;
         public static readonly STEP_GATHERRENDERTARGETS_GEOMETRYBUFFERRENDERER = 1;

+ 1 - 0
tests/validation/validate.html

@@ -6,6 +6,7 @@
     <script src="https://preview.babylonjs.com/draco_decoder.js"></script>
     <script src="https://preview.babylonjs.com/cannon.js"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
+    <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
     <script src="https://preview.babylonjs.com/babylon.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>