Browse Source

Merge pull request #7498 from bghgary/glb-fixes

Remove dependency on Content-Range for GLB
David Catuhe 5 years ago
parent
commit
8c350b466a
1 changed files with 25 additions and 33 deletions
  1. 25 33
      loaders/src/glTF/glTFFileLoader.ts

+ 25 - 33
loaders/src/glTF/glTFFileLoader.ts

@@ -486,7 +486,10 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
                     readAsync: (byteOffset: number, byteLength: number) => {
                         return new Promise<ArrayBufferView>((resolve, reject) => {
                             fileRequests.push(scene._requestFile(url, (data, webRequest) => {
-                                dataBuffer.byteLength = Number(webRequest!.getResponseHeader("Content-Range")!.split("/")[1]);
+                                const contentRange = webRequest!.getResponseHeader("Content-Range");
+                                if (contentRange) {
+                                    dataBuffer.byteLength = Number(contentRange.split("/")[1]);
+                                }
                                 resolve(new Uint8Array(data as ArrayBuffer));
                             }, onProgress, true, true, (error) => {
                                 reject(error);
@@ -727,18 +730,18 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
             }
 
             const length = dataReader.readUint32();
-            if (length !== dataReader.buffer.byteLength) {
+            if (dataReader.buffer.byteLength != 0 && length !== dataReader.buffer.byteLength) {
                 throw new Error(`Length in header does not match actual data length: ${length} != ${dataReader.buffer.byteLength}`);
             }
 
             let unpacked: Promise<IGLTFLoaderData>;
             switch (version) {
                 case 1: {
-                    unpacked = this._unpackBinaryV1Async(dataReader);
+                    unpacked = this._unpackBinaryV1Async(dataReader, length);
                     break;
                 }
                 case 2: {
-                    unpacked = this._unpackBinaryV2Async(dataReader);
+                    unpacked = this._unpackBinaryV2Async(dataReader, length);
                     break;
                 }
                 default: {
@@ -752,7 +755,7 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
         });
     }
 
-    private _unpackBinaryV1Async(dataReader: DataReader): Promise<IGLTFLoaderData> {
+    private _unpackBinaryV1Async(dataReader: DataReader, length: number): Promise<IGLTFLoaderData> {
         const ContentFormat = {
             JSON: 0
         };
@@ -764,7 +767,7 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
             throw new Error(`Unexpected content format: ${contentFormat}`);
         }
 
-        const bodyLength = dataReader.buffer.byteLength - dataReader.byteOffset;
+        const bodyLength = length - dataReader.byteOffset;
 
         const data: IGLTFLoaderData = { json: this._parseJson(dataReader.readString(contentLength)), bin: null };
         if (bodyLength !== 0) {
@@ -778,37 +781,26 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
         return Promise.resolve(data);
     }
 
-    private _unpackBinaryV2Async(dataReader: DataReader): Promise<IGLTFLoaderData> {
+    private _unpackBinaryV2Async(dataReader: DataReader, length: number): Promise<IGLTFLoaderData> {
         const ChunkFormat = {
             JSON: 0x4E4F534A,
             BIN: 0x004E4942
         };
 
-        // Read the JSON chunk header.
-        const chunkLength = dataReader.readUint32();
-        const chunkFormat = dataReader.readUint32();
-        if (chunkFormat !== ChunkFormat.JSON) {
-            throw new Error("First chunk format is not JSON");
-        }
+        const data: IGLTFLoaderData = { json: {}, bin: null };
 
-        // Bail if there are no other chunks.
-        if (dataReader.byteOffset + chunkLength === dataReader.buffer.byteLength) {
-            return dataReader.loadAsync(chunkLength).then(() => {
-                return { json: this._parseJson(dataReader.readString(chunkLength)), bin: null };
-            });
-        }
+        const readAsync = (): Promise<IGLTFLoaderData> => {
+            const chunkLength = dataReader.readUint32();
+            const chunkFormat = dataReader.readUint32();
 
-        // Read the JSON chunk and the length and type of the next chunk.
-        return dataReader.loadAsync(chunkLength + 8).then(() => {
-            const data: IGLTFLoaderData = { json: this._parseJson(dataReader.readString(chunkLength)), bin: null };
-
-            const readAsync = (): Promise<IGLTFLoaderData> => {
-                const chunkLength = dataReader.readUint32();
-                const chunkFormat = dataReader.readUint32();
+            const finalChunk = (dataReader.byteOffset + chunkLength + 8 > length);
 
+            // Read the chunk and (if available) the length and type of the next chunk.
+            return dataReader.loadAsync(finalChunk ? chunkLength : chunkLength + 8).then(() => {
                 switch (chunkFormat) {
                     case ChunkFormat.JSON: {
-                        throw new Error("Unexpected JSON chunk");
+                        data.json = this._parseJson(dataReader.readString(chunkLength));
+                        break;
                     }
                     case ChunkFormat.BIN: {
                         const startByteOffset = dataReader.byteOffset;
@@ -826,15 +818,15 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
                     }
                 }
 
-                if (dataReader.byteOffset !== dataReader.buffer.byteLength) {
-                    return dataReader.loadAsync(8).then(readAsync);
+                if (finalChunk) {
+                    return data;
                 }
 
-                return Promise.resolve(data);
-            };
+                return readAsync();
+            });
+        };
 
-            return readAsync();
-        });
+        return readAsync();
     }
 
     private static _parseVersion(version: string): Nullable<{ major: number, minor: number }> {