Thanks for all your work on Spark — really enjoying working with it.
We serve our .rad files with a simple encryption layer on top, and we need to decrypt them on load, but there's currently no hook or entry point to do that.
fetchRange() in SplatPager.ts is entirely internal to the module, and both the RAD header fetch and the chunk fetches go through it, so there's no way to hook into it from the outside. requestHeader / withCredentials can be set via PagedSplatsOptions (not from SplatMesh itself currently), but that only controls request headers and credentials — there's no way to actually customize or replace what fetchRange does.
Right now, we're patching the built dist/spark.module.js directly to splice our own logic in. While this works, it means re-applying the patch on every release — not great for maintenance. We're also probably not the only ones who'd want to hook into fetching for one reason or another (authenticated fetches, a custom CDN, mocking in tests, etc.), and it'd be nice if people didn't all have to independently build and maintain the same kind of dist patch.
So, it'd be great if the fetchRange implementation itself could be injected via PagedSplatsOptions. Something like:
const paged = new PagedSplats({
rootUrl: "https://example.com/scene.rad",
fetchRange: async ({ url, offset, bytes, requestHeader, withCredentials, signal }) => {
// custom fetch implementation goes here
return myCustomFetch({ url, offset, bytes, requestHeader, withCredentials, signal });
},
});
If the default fetchRange implementation (the current fetch()-based behavior) stays exported, not passing this option would leave the existing behavior unchanged.
Beyond decryption, this seems useful for things like fetching through a custom CDN/proxy or mocking in tests, so I think it's worth framing as a general-purpose hook rather than something decryption-specific. (Non-paged loading goes through a separate fetch path, so I'd scope this to just the RAD/paged fetchRange for now.)
#297 (Add injectable LOD runtime interfaces) added a similar non-breaking injectable seam for the LOD/sort pipeline, so that seems like a reasonable pattern to follow here.
If this direction looks good, I'll go ahead and put up a PR. Let me know if something like this has already been discussed somewhere — happy to be pointed there instead.
Thanks for all your work on Spark — really enjoying working with it.
We serve our
.radfiles with a simple encryption layer on top, and we need to decrypt them on load, but there's currently no hook or entry point to do that.fetchRange()inSplatPager.tsis entirely internal to the module, and both the RAD header fetch and the chunk fetches go through it, so there's no way to hook into it from the outside.requestHeader/withCredentialscan be set viaPagedSplatsOptions(not fromSplatMeshitself currently), but that only controls request headers and credentials — there's no way to actually customize or replace whatfetchRangedoes.Right now, we're patching the built
dist/spark.module.jsdirectly to splice our own logic in. While this works, it means re-applying the patch on every release — not great for maintenance. We're also probably not the only ones who'd want to hook into fetching for one reason or another (authenticated fetches, a custom CDN, mocking in tests, etc.), and it'd be nice if people didn't all have to independently build and maintain the same kind of dist patch.So, it'd be great if the
fetchRangeimplementation itself could be injected viaPagedSplatsOptions. Something like:If the default
fetchRangeimplementation (the currentfetch()-based behavior) stays exported, not passing this option would leave the existing behavior unchanged.Beyond decryption, this seems useful for things like fetching through a custom CDN/proxy or mocking in tests, so I think it's worth framing as a general-purpose hook rather than something decryption-specific. (Non-paged loading goes through a separate fetch path, so I'd scope this to just the RAD/paged fetchRange for now.)
#297 (Add injectable LOD runtime interfaces) added a similar non-breaking injectable seam for the LOD/sort pipeline, so that seems like a reasonable pattern to follow here.
If this direction looks good, I'll go ahead and put up a PR. Let me know if something like this has already been discussed somewhere — happy to be pointed there instead.