Skip to content

Commit

Permalink
Support for Chunked Data, Refactored Loaders (#57)
Browse files Browse the repository at this point in the history
* Added support for chunked data (it doesnt include content-length in the header)
* Added `LoadersUtils.ts` to remove the repeated code in the `PLYLoaders.ts` and `Loaders.ts` files
  • Loading branch information
TravisThomp authored Feb 6, 2024
1 parent 4933ddf commit 9080a5a
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 50 deletions.
28 changes: 3 additions & 25 deletions src/loaders/Loader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Scene } from "../core/Scene";
import { Splat } from "../splats/Splat";
import { SplatData } from "../splats/SplatData";
import { initiateFetchRequest, loadRequestDataIntoBuffer } from "../utils/LoaderUtils";

class Loader {
static async LoadAsync(
Expand All @@ -9,32 +10,9 @@ class Loader {
onProgress?: (progress: number) => void,
useCache: boolean = false,
): Promise<Splat> {
const req = await fetch(url, {
mode: "cors",
credentials: "omit",
cache: useCache ? "force-cache" : "default",
});

if (req.status != 200) {
throw new Error(req.status + " Unable to load " + req.url);
}

const reader = req.body!.getReader();
const contentLength = parseInt(req.headers.get("content-length") as string);
const buffer = new Uint8Array(contentLength);

let bytesRead = 0;

// eslint-disable-next-line no-constant-condition
while (true) {
const { done, value } = await reader.read();
if (done) break;

buffer.set(value, bytesRead);
bytesRead += value.length;
const res: Response = await initiateFetchRequest(url, useCache);

onProgress?.(bytesRead / contentLength);
}
const buffer = await loadRequestDataIntoBuffer(res, onProgress);

const data = SplatData.Deserialize(buffer);
const splat = new Splat(data);
Expand Down
28 changes: 3 additions & 25 deletions src/loaders/PLYLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Quaternion } from "../math/Quaternion";
import { SplatData } from "../splats/SplatData";
import { Splat } from "../splats/Splat";
import { Converter } from "../utils/Converter";
import { initiateFetchRequest, loadRequestDataIntoBuffer } from "../utils/LoaderUtils";

class PLYLoader {
static async LoadAsync(
Expand All @@ -13,32 +14,9 @@ class PLYLoader {
format: string = "",
useCache: boolean = false,
): Promise<Splat> {
const req = await fetch(url, {
mode: "cors",
credentials: "omit",
cache: useCache ? "force-cache" : "default",
});

if (req.status != 200) {
throw new Error(req.status + " Unable to load " + req.url);
}

const reader = req.body!.getReader();
const contentLength = parseInt(req.headers.get("content-length") as string);
const plyData = new Uint8Array(contentLength);
const res: Response = await initiateFetchRequest(url, useCache);

let bytesRead = 0;

// eslint-disable-next-line no-constant-condition
while (true) {
const { done, value } = await reader.read();
if (done) break;

plyData.set(value, bytesRead);
bytesRead += value.length;

onProgress?.(bytesRead / contentLength);
}
const plyData = await loadRequestDataIntoBuffer(res, onProgress);

if (plyData[0] !== 112 || plyData[1] !== 108 || plyData[2] !== 121 || plyData[3] !== 10) {
throw new Error("Invalid PLY file");
Expand Down
74 changes: 74 additions & 0 deletions src/utils/LoaderUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
export async function initiateFetchRequest(url: string, useCache: boolean): Promise<Response> {
const req = await fetch(url, {
mode: "cors",
credentials: "omit",
cache: useCache ? "force-cache" : "default",
});

if (req.status != 200) {
throw new Error(req.status + " Unable to load " + req.url);
}

return req;
}

export async function loadDataIntoBuffer(res: Response, onProgress?: (progress: number) => void): Promise<Uint8Array> {
const reader = res.body!.getReader();

const contentLength = parseInt(res.headers.get("content-length") as string);
const buffer = new Uint8Array(contentLength);

let bytesRead = 0;

// eslint-disable-next-line no-constant-condition
while (true) {
const { done, value } = await reader.read();
if (done) break;

buffer.set(value, bytesRead);
bytesRead += value.length;
onProgress?.(bytesRead / contentLength);
}

return buffer;
}

export async function loadChunkedDataIntoBuffer(
res: Response,
onProgress?: (progress: number) => void,
): Promise<Uint8Array> {
const reader = res.body!.getReader();

const chunks = [];
let receivedLength = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
const { done, value } = await reader.read();
if (done) break;

chunks.push(value);
receivedLength += value.length;
}

const buffer = new Uint8Array(receivedLength);
let position = 0;
for (const chunk of chunks) {
buffer.set(chunk, position);
position += chunk.length;

onProgress?.(position / receivedLength);
}

return buffer;
}

export async function loadRequestDataIntoBuffer(
res: Response,
onProgress?: (progress: number) => void,
): Promise<Uint8Array> {
if (res.headers.has("content-length")) {
return loadDataIntoBuffer(res, onProgress);
} else {
return loadChunkedDataIntoBuffer(res, onProgress);
}
}

0 comments on commit 9080a5a

Please sign in to comment.