瀏覽代碼

Revert bad change to glTF range request
Update unit test to check for expected range requests

Gary Hsu 5 年之前
父節點
當前提交
1075a701e4
共有 2 個文件被更改,包括 42 次插入16 次删除
  1. 26 15
      loaders/src/glTF/glTFFileLoader.ts
  2. 16 1
      tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.ts

+ 26 - 15
loaders/src/glTF/glTFFileLoader.ts

@@ -787,20 +787,31 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
             BIN: 0x004E4942
         };
 
-        const data: IGLTFLoaderData = { json: {}, bin: null };
+        // 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 readAsync = (): Promise<IGLTFLoaderData> => {
-            const chunkLength = dataReader.readUint32();
-            const chunkFormat = dataReader.readUint32();
+        // 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 finalChunk = (dataReader.byteOffset + chunkLength + 8 > length);
+        // 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();
 
-            // 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: {
-                        data.json = this._parseJson(dataReader.readString(chunkLength));
-                        break;
+                        throw new Error("Unexpected JSON chunk");
                     }
                     case ChunkFormat.BIN: {
                         const startByteOffset = dataReader.byteOffset;
@@ -818,15 +829,15 @@ export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISc
                     }
                 }
 
-                if (finalChunk) {
-                    return data;
+                if (dataReader.byteOffset !== dataReader.buffer.byteLength) {
+                    return dataReader.loadAsync(8).then(readAsync);
                 }
 
-                return readAsync();
-            });
-        };
+                return Promise.resolve(data);
+            };
 
-        return readAsync();
+            return readAsync();
+        });
     }
 
     private static _parseVersion(version: string): Nullable<{ major: number, minor: number }> {

+ 16 - 1
tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.ts

@@ -404,13 +404,28 @@ describe('Babylon Scene Loader', function() {
             const scene = new BABYLON.Scene(subject);
             const promises = new Array<Promise<void>>();
 
+            const expectedSetRequestHeaderCalls = [
+                "Range: bytes=0-19",
+                "Range: bytes=20-1399",
+                "Range: bytes=1400-1817",
+                "Range: bytes=1820-3149",
+                "Range: bytes=3152-8841",
+            ];
+
+            const setRequestHeaderCalls = new Array<string>();
+            const origSetRequestHeader = BABYLON.WebRequest.prototype.setRequestHeader;
+            sinon.stub(BABYLON.WebRequest.prototype, "setRequestHeader").callsFake(function(...args) {
+                setRequestHeaderCalls.push(args.join(": "));
+                origSetRequestHeader.apply(this, args);
+            });
+
             BABYLON.SceneLoader.OnPluginActivatedObservable.addOnce((loader: BABYLON.GLTFFileLoader) => {
                 loader.useRangeRequests = true;
                 promises.push(loader.whenCompleteAsync());
             });
 
             promises.push(BABYLON.SceneLoader.AppendAsync("/Playground/scenes/", "LevelOfDetail.glb", scene).then(() => {
-                // do nothing
+                expect(setRequestHeaderCalls, "setRequestHeaderCalls").to.have.ordered.members(expectedSetRequestHeaderCalls);
             }));
 
             return Promise.all(promises);