mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-20 20:22:09 +00:00
ifcviewer-web: stream remote sidecars over HTTP Range (?model=URL)
Adds a network byte-source alongside the local Blob one. The async-chunk
infra is source-agnostic — only the two JS primitives knew it was a Blob —
so this generalises them and reuses everything else:
- ifcvReadRangeInto: local → Blob.slice; remote → fetch() with a Range
header (206). If a server ignores Range and returns 200, the requested
window is sliced out so it still works (without the bandwidth saving).
- ifcvFileSize: Blob size, or the URL's total length resolved up front.
- ifcvBeginUrlSource: resolves total size (HEAD Content-Length, else a
0-0 ranged GET's Content-Range) then fires _ifcv_source_ready.
- The metadata bootstrap is extracted into a source-agnostic
loadSidecarMetadataWeb(label); loadSidecarFromBlobWeb / FromUrlWeb are
thin entries. streaming_from_blob → streaming_from_web (now covers both).
main_web exports load_sidecar_from_url_c(url); shell.html reads a
?model=URL query param and ccalls it once the app is live (same-origin
needs no CORS; cross-origin hosts must send CORS + Accept-Ranges).
Test: serve.mjs now answers HEAD + Range (206) and falls back to the
ifcviewer-web source dir for sample.ifcview (embedded in the wasm, not in
build-web). New smoke case loads ?model=/sample.ifcview and asserts it
renders via the Range path. 6/6 web smoke + 107/107 unit pass; desktop
unaffected (web-guarded; only the shared field rename touches it).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -357,19 +357,24 @@ public:
|
||||
std::uint32_t loadSidecarFromPath(const std::string& path);
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
// Web byte-range load (#88). Loads a sidecar from the JS-registered
|
||||
// File (Module.__ifcvFile) WITHOUT copying the whole file into the
|
||||
// wasm heap: the head + tail metadata are read via Blob.slice, the
|
||||
// streaming model is built, and it is tagged blob-sourced so each
|
||||
// chunk's vertex/index byte ranges are pulled lazily through the async
|
||||
// path. Asynchronous — returns immediately and frames the model from
|
||||
// the JS completion callback. resetScene() first to replace.
|
||||
// Web byte-range load (#88). Streams a sidecar from a JS-side source
|
||||
// WITHOUT copying the whole file into the wasm heap: head + tail metadata
|
||||
// are read via byte ranges, the streaming model is built, and it is tagged
|
||||
// web-sourced so each chunk's vertex/index ranges are pulled lazily.
|
||||
// Asynchronous — returns immediately and frames the model from the JS
|
||||
// completion callback. resetScene() first to replace.
|
||||
//
|
||||
// - Blob: the picked File on Module.__ifcvFile (Blob.slice).
|
||||
// - URL: a remote sidecar (HTTP Range); resolves total size first, then
|
||||
// runs the shared bootstrap via the ifcv_source_ready callback.
|
||||
void loadSidecarFromBlobWeb();
|
||||
void loadSidecarFromUrlWeb(std::string url);
|
||||
void loadSidecarMetadataWeb(std::string source_label);
|
||||
|
||||
// Kick off the async blob read of one chunk's vertex + index byte
|
||||
// ranges. applyStreamedChunk runs in the JS completion callback;
|
||||
// c.is_loading is held until then. No-op if the model/chunk vanished
|
||||
// mid-flight (e.g. a resetScene landed between issue and completion).
|
||||
// Kick off the async read of one chunk's vertex + index byte ranges (from
|
||||
// the active web source). applyStreamedChunk runs in the JS completion
|
||||
// callback; c.is_loading is held until then. No-op if the model/chunk
|
||||
// vanished mid-flight (e.g. a resetScene landed between issue and done).
|
||||
void beginWebChunkLoad(std::uint32_t model_id, std::size_t chunk_idx);
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user