Kaynağa Gözat

Add support for preprocessing urls in glTF loader

Gary Hsu 7 yıl önce
ebeveyn
işleme
430daa056c

+ 8 - 10
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -1568,18 +1568,16 @@ module BABYLON.GLTF1 {
         public compileMaterials = false;
         public useClipPlane = false;
         public compileShadowGenerators = false;
+        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
 
-        public onDisposeObservable = new Observable<IGLTFLoader>();
-        public onMeshLoadedObservable = new Observable<AbstractMesh>();
-        public onTextureLoadedObservable = new Observable<BaseTexture>();
-        public onMaterialLoadedObservable = new Observable<Material>();
-        public onCameraLoadedObservable = new Observable<Camera>();
-        public onCompleteObservable = new Observable<IGLTFLoader>();
-        public onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
+        public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
+        public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
+        public readonly onMaterialLoadedObservable = new Observable<Material>();
+        public readonly onCameraLoadedObservable = new Observable<Camera>();
+        public readonly onCompleteObservable = new Observable<IGLTFLoader>();
+        public readonly onDisposeObservable = new Observable<IGLTFLoader>();
+        public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
 
-        /**
-        * State of the loader
-        */
         public state: Nullable<GLTFLoaderState> = null;
 
         public dispose(): void {}

+ 46 - 36
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -39,20 +39,20 @@ module BABYLON.GLTF2 {
         private _progressCallback?: (event: SceneLoaderProgressEvent) => void;
         private _requests = new Array<IFileRequestInfo>();
 
-        private static _Names = new Array<string>();
-        private static _Factories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
+        private static _ExtensionNames = new Array<string>();
+        private static _ExtensionFactories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
 
         /** @hidden */
         public static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void {
-            if (GLTFLoader._Factories[name]) {
+            if (GLTFLoader._ExtensionFactories[name]) {
                 Tools.Error(`Extension with the name '${name}' already exists`);
                 return;
             }
 
-            GLTFLoader._Factories[name] = factory;
+            GLTFLoader._ExtensionFactories[name] = factory;
 
             // Keep the order of registration so that extensions registered first are called first.
-            GLTFLoader._Names.push(name);
+            GLTFLoader._ExtensionNames.push(name);
         }
 
         /**
@@ -81,6 +81,11 @@ module BABYLON.GLTF2 {
         public compileShadowGenerators = false;
 
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
+
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
@@ -118,7 +123,6 @@ module BABYLON.GLTF2 {
          */
         public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
 
-
         /**
          * Loader state or null if the loader is not active.
          */
@@ -254,15 +258,17 @@ module BABYLON.GLTF2 {
 
                 return resultPromise;
             }).catch(error => {
-                Tools.Error(`glTF Loader: ${error.message}`);
-                this._clear();
-                throw error;
+                if (!this._disposed) {
+                    Tools.Error(`glTF Loader: ${error.message}`);
+                    this._clear();
+                    throw error;
+                }
             });
         }
 
         private _loadExtensions(): void {
-            for (const name of GLTFLoader._Names) {
-                const extension = GLTFLoader._Factories[name](this);
+            for (const name of GLTFLoader._ExtensionNames) {
+                const extension = GLTFLoader._ExtensionFactories[name](this);
                 this._extensions[name] = extension;
 
                 this.onExtensionLoadedObservable.notifyObservers(extension);
@@ -1516,33 +1522,37 @@ module BABYLON.GLTF2 {
                 return Promise.resolve(new Uint8Array(Tools.DecodeBase64(uri)));
             }
 
-            return new Promise((resolve, reject) => {
-                const request = Tools.LoadFile(this._rootUrl + uri, data => {
-                    if (!this._disposed) {
-                        resolve(new Uint8Array(data as ArrayBuffer));
-                    }
-                }, event => {
+            return this.preprocessUrlAsync(this._rootUrl + uri).then(url => {
+                return new Promise<ArrayBufferView>((resolve, reject) => {
                     if (!this._disposed) {
-                        try {
-                            if (request && this._state === GLTFLoaderState.LOADING) {
-                                request._lengthComputable = event.lengthComputable;
-                                request._loaded = event.loaded;
-                                request._total = event.total;
-                                this._onProgress();
+                        const request = Tools.LoadFile(url, data => {
+                            if (!this._disposed) {
+                                resolve(new Uint8Array(data as ArrayBuffer));
                             }
-                        }
-                        catch (e) {
-                            reject(e);
-                        }
-                    }
-                }, this._babylonScene.database, true, (request, exception) => {
-                    if (!this._disposed) {
-                        reject(new LoadFileError(`${context}: Failed to load '${uri}'${request ? ": " + request.status + " " + request.statusText : ""}`, request));
-                    }
-                }) as IFileRequestInfo;
+                        }, event => {
+                            if (!this._disposed) {
+                                try {
+                                    if (request && this._state === GLTFLoaderState.LOADING) {
+                                        request._lengthComputable = event.lengthComputable;
+                                        request._loaded = event.loaded;
+                                        request._total = event.total;
+                                        this._onProgress();
+                                    }
+                                }
+                                catch (e) {
+                                    reject(e);
+                                }
+                            }
+                        }, this._babylonScene.database, true, (request, exception) => {
+                            if (!this._disposed) {
+                                reject(new LoadFileError(`${context}: Failed to load '${uri}'${request ? ": " + request.status + " " + request.statusText : ""}`, request));
+                            }
+                        }) as IFileRequestInfo;
 
-                this._requests.push(request);
-            })
+                        this._requests.push(request);
+                    }
+                });
+            });
         }
 
         private _onProgress(): void {
@@ -1762,7 +1772,7 @@ module BABYLON.GLTF2 {
 
         /** @hidden */
         public _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>) {
-            for (const name of GLTFLoader._Names) {
+            for (const name of GLTFLoader._ExtensionNames) {
                 const extension = this._extensions[name];
                 if (extension.enabled) {
                     const promise = actionAsync(extension);

+ 13 - 0
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -116,6 +116,11 @@ module BABYLON {
         compileShadowGenerators: boolean;
 
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -249,6 +254,11 @@ module BABYLON {
         public compileShadowGenerators = false;
 
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
+
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
@@ -415,6 +425,8 @@ module BABYLON {
                 this._loader = null;
             }
 
+            this.preprocessUrlAsync = url => Promise.resolve(url);
+
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -560,6 +572,7 @@ module BABYLON {
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(mesh => this.onMeshLoadedObservable.notifyObservers(mesh));
             loader.onTextureLoadedObservable.add(texture => this.onTextureLoadedObservable.notifyObservers(texture));
             loader.onMaterialLoadedObservable.add(material => this.onMaterialLoadedObservable.notifyObservers(material));