Browse Source

Merge pull request #8435 from Popov72/sceneloader-base64-support

Added support for .glb file loading through a base64 encoded filename
sebavan 5 years ago
parent
commit
f1cf007e34

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

@@ -102,6 +102,7 @@
 - Improved progress handling in glTF loader. ([bghgary](https://github.com/bghgary))
 - Use min/max values from position accessors (when available) to set the bounding box of meshes ([Popov72](https://github.com/Popov72))
 - Added missing "pluginExtension" parameter to SceneLoader.ImportAnimations. ([phenry20](https://github.com/phenry20))
+- Added support for .glb file loading through a base64 encoded filename ([Popov72](https://github.com/Popov72))
 
 ### Serializers
 

+ 21 - 3
loaders/src/glTF/glTFFileLoader.ts

@@ -20,6 +20,7 @@ import { GLTFValidation } from './glTFValidation';
 import { Light } from 'babylonjs/Lights/light';
 import { TransformNode } from 'babylonjs/Meshes/transformNode';
 import { RequestFileError } from 'babylonjs/Misc/fileTools';
+import { StringTools } from 'babylonjs/Misc/stringTools';
 
 interface IFileRequestInfo extends IFileRequest {
     _lengthComputable?: boolean;
@@ -456,6 +457,8 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
     private _progressCallback?: (event: ISceneLoaderProgressEvent) => void;
     private _requests = new Array<IFileRequestInfo>();
 
+    private static magicBase64Encoded = "Z2xURg"; // "glTF" base64 encoded (without the quotes!)
+
     /**
      * Name of the loader ("gltf")
      */
@@ -634,13 +637,28 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
 
     /** @hidden */
     public canDirectLoad(data: string): boolean {
-        return data.indexOf("asset") !== -1 && data.indexOf("version") !== -1;
+        return (data.indexOf("asset") !== -1 && data.indexOf("version") !== -1)
+                || StringTools.StartsWith(data, "data:base64," + GLTFFileLoader.magicBase64Encoded)
+                || StringTools.StartsWith(data, "data:application/octet-stream;base64," + GLTFFileLoader.magicBase64Encoded)
+                || StringTools.StartsWith(data, "data:model/gltf-binary;base64," + GLTFFileLoader.magicBase64Encoded);
     }
 
     /** @hidden */
-    public directLoad(scene: Scene, data: string): any {
+    public directLoad(scene: Scene, data: string): Promise<any> {
+        if (StringTools.StartsWith(data, "base64," + GLTFFileLoader.magicBase64Encoded) ||
+            StringTools.StartsWith(data, "application/octet-stream;base64," + GLTFFileLoader.magicBase64Encoded) ||
+            StringTools.StartsWith(data, "model/gltf-binary;base64," + GLTFFileLoader.magicBase64Encoded)) {
+            const arrayBuffer = Tools.DecodeBase64(data);
+
+            this._validate(scene, arrayBuffer);
+            return this._unpackBinaryAsync(new DataReader({
+                readAsync: (byteOffset, byteLength) => Promise.resolve(new Uint8Array(arrayBuffer, byteOffset, byteLength)),
+                byteLength: arrayBuffer.byteLength
+            }));
+        }
+
         this._validate(scene, data);
-        return { json: this._parseJson(data) };
+        return Promise.resolve({ json: this._parseJson(data) });
     }
 
     /**

+ 10 - 2
src/Loading/sceneLoader.ts

@@ -123,7 +123,7 @@ export interface ISceneLoaderPluginBase {
      * @param data string containing the data
      * @returns data to pass to the plugin
      */
-    directLoad?(scene: Scene, data: string): any;
+    directLoad?(scene: Scene, data: string): Promise<any>;
 
     /**
      * The callback that allows custom handling of the root url based on the response url.
@@ -417,7 +417,15 @@ export class SceneLoader {
         SceneLoader.OnPluginActivatedObservable.notifyObservers(plugin);
 
         if (directLoad) {
-            onSuccess(plugin, plugin.directLoad ? plugin.directLoad(scene, directLoad) : directLoad);
+            if (plugin.directLoad) {
+                plugin.directLoad(scene, directLoad).then((data) => {
+                    onSuccess(plugin, data);
+                }).catch((error) => {
+                    onError("Error in directLoad of _loadData: " + error, error);
+                });
+            } else {
+                onSuccess(plugin, directLoad);
+            }
             return plugin;
         }