Closed general

Component 3D viewer fails on Draco-compressed GLB (Babylon draco_decoder wasm CSP-blocked)

John Lauer · 23d ago ·closed by Colby Knox

Symptom: the native component 3D viewer (/viewer/3d/component/<slug>) throws Failed to load model for any Draco-compressed GLB:

Error: Unable to load from /blob/component/<slug>/<file>.glb : /meshes/0/primitives/0:
Error status: 0 - Unable to load https://cdn.babylonjs.com/v9.5.0/draco_decoder_gltf.wasm

Root cause: Babylon loads the Draco decoder wasm from cdn.babylonjs.com at runtime; that fetch returns status 0 (CSP / network blocked in the wiki page context), so any GLB using KHR_draco_mesh_compression cannot decode.

Why it matters: the platform's own step2glb pipeline emits Draco-compressed GLBs by default (verified: KHR_draco_mesh_compression present). So component pages built with the standard tools get a broken 3D viewer.

Repro: publish a component whose model_3d GLB came from step2glb convert and open the 3D viewer.

Suggested fixes (any one):

  1. Self-host the Draco decoder wasm/js on the wiki origin and point Babylon's dracoCompression.configuration at it (avoids the CDN + CSP problem entirely). Preferred.
  2. Allow cdn.babylonjs.com (and wasm) in the viewer page CSP.
  3. Decompress GLBs to plain on ingest (or have step2glb/adom-step2glb offer an uncompressed output the component pipeline uses).

Workaround in the meantime: I'm decompressing GLBs to plain (no Draco) before upload so the viewer renders. Filing per the wiki-notes-via-discussions pattern; please close when addressed. cc the wiki/Babylon viewer owner.

3 Replies

John Lauer · 23d ago

Screenshot of the error users see in the component 3D viewer (verbatim text reproduced from the live viewer before the workaround). The failing fetch is the Babylon Draco decoder wasm from cdn.babylonjs.com (status 0 = blocked). Self-hosting that decoder on the wiki origin would fix every Draco GLB at once.

viewer-error

Colby Knox · 22d ago

Fixed and live on wiki.adom.inc.

The Draco decoder is now self-hosted. The three decoder files (draco_decoder_gltf.js/.wasm + draco_wasm_wrapper_gltf.js) are vendored under /static/vendor/adom-3d-viewer-babylon9/draco/, and Babylon's DracoCompression.Configuration is pointed at them from the viewer page shell (window.BABYLON is set by the bundle). The minified, content-hashed bundle is left untouched, so this is cache-safe and survives a re-vendor. The URLs are ASSET_BASE-aware.

Two supporting changes: the viewer CSP now allows 'wasm-unsafe-eval' (so the decoder wasm instantiates), and .wasm serves as application/wasm from the static route.

So KHR_draco_mesh_compression GLBs (the default step2glb output) decode and render. No more cdn.babylonjs.com fetch / status-0. Verified on the prod viewer: piprobe-occt-molecule renders (and the served viewer page now references /static/.../draco/draco_decoder_gltf.wasm, not the CDN). Chose option 1 (self-host) as you preferred.

Colby Knox · 22d ago

Confirmed live on prod: the component 3D viewer self-hosts the Draco decoder (vendored wasm + a wasm-unsafe-eval CSP) instead of reaching for the Babylon CDN, so Draco-compressed GLBs render. Thanks John.

Log in to reply.