Use fetch instead of FileLoader in SplatLoader to avoid reusing same arraybuffer (#94)

This commit is contained in:
Noeri Huisman
2025-07-11 20:37:20 +02:00
committed by GitHub
parent 30d639a362
commit bc4f5137c6
+32 -18
View File
@@ -7,7 +7,7 @@ import { withWorker } from "./splatWorker";
import { decompressPartialGzip, getTextureSize } from "./utils"; import { decompressPartialGzip, getTextureSize } from "./utils";
// SplatLoader implements the THREE.Loader interface and supports loading a variety // SplatLoader implements the THREE.Loader interface and supports loading a variety
// of differeng Gsplat file formats. Formats .PLY and .SPZ can be auto-detected // of different Gsplat file formats. Formats .PLY and .SPZ can be auto-detected
// from the file contents, while .SPLAT and .KSPLAT require either having the // from the file contents, while .SPLAT and .KSPLAT require either having the
// appropriate file extension as part of the path, or it can be explicitly set // appropriate file extension as part of the path, or it can be explicitly set
// in the loader using the fileType property. // in the loader using the fileType property.
@@ -28,20 +28,29 @@ export class SplatLoader extends Loader {
onProgress?: (event: ProgressEvent) => void, onProgress?: (event: ProgressEvent) => void,
onError?: (error: unknown) => void, onError?: (error: unknown) => void,
) { ) {
this.fileLoader.setResponseType("arraybuffer"); const resolvedURL = this.manager.resolveURL(
this.fileLoader.setCrossOrigin(this.crossOrigin); (this.path ?? "") + (url ?? ""),
this.fileLoader.setWithCredentials(this.withCredentials); );
this.fileLoader.setPath(this.path);
this.fileLoader.setResourcePath(this.resourcePath); // create request
this.fileLoader.setRequestHeader(this.requestHeader); const req = new Request(resolvedURL, {
this.fileLoader.load( headers: new Headers(this.requestHeader),
url, credentials: this.withCredentials ? "include" : "same-origin",
async (response) => { });
let fileType = this.fileType;
fetch(req)
.then(async (response) => {
if (!response.ok) {
throw new Error(
`${response.status} "${response.statusText}" fetching URL: ${resolvedURL}`,
);
}
if (onLoad) { if (onLoad) {
const input = response as ArrayBuffer; const input = await response.arrayBuffer();
const extraFiles: Record<string, ArrayBuffer> = {}; const extraFiles: Record<string, ArrayBuffer> = {};
const promises = []; const promises = [];
let fileType = this.fileType;
try { try {
const pcSogsJson = tryPcSogs(input); const pcSogsJson = tryPcSogs(input);
@@ -58,7 +67,7 @@ export class SplatLoader extends Loader {
if (prop) { if (prop) {
const files = prop.files; const files = prop.files;
for (const file of files) { for (const file of files) {
const fileUrl = new URL(file, url).toString(); const fileUrl = new URL(file, resolvedURL).toString();
this.manager.itemStart(fileUrl); this.manager.itemStart(fileUrl);
const promise = this.loadExtra(fileUrl) const promise = this.loadExtra(fileUrl)
.then((data) => { .then((data) => {
@@ -82,7 +91,7 @@ export class SplatLoader extends Loader {
input, input,
extraFiles, extraFiles,
fileType, fileType,
pathOrUrl: url, pathOrUrl: resolvedURL,
}); });
if (this.packedSplats) { if (this.packedSplats) {
@@ -95,10 +104,15 @@ export class SplatLoader extends Loader {
onError?.(error); onError?.(error);
} }
} }
}, })
onProgress, .catch((error) => {
onError, onError?.(error);
); })
.finally(() => {
this.manager.itemEnd(resolvedURL);
});
this.manager.itemStart(resolvedURL);
} }
async loadAsync( async loadAsync(