Support Draco mesh decoding in Node via worker_threads#8951
Merged
Conversation
Draco glb loading failed in Node because the decoder unconditionally used browser-only APIs (Blob, URL.createObjectURL, web Worker) and the worker body talked to `self`. Branch on platform.environment === 'node' to spawn a worker_threads worker and route messages, mirroring the existing gsplat sorter. Fixes #8524
Build size reportThis PR changes the size of the minified bundles.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #8524. Draco glb loading failed in Node:
initializeWorkersindraco-decoder.jsunconditionally used browser-only APIs (Blob,URL.createObjectURL, the webWorkerconstructor), and the worker body indraco-worker.jstalked toself— none of which exist in a Nodeworker_threadsworker.This branches on
platform.environment === 'node'to useworker_threads, mirroring the existinggsplat-sorter/gsplat-sort-workerpattern already in the engine.Changes:
draco-worker.js: resolve the worker scope asconst myself = (typeof self !== 'undefined' && self) || require('node:worker_threads').parentPort;and usemyself.postMessage/myself.addEventListener('message', …)instead ofself. The decoder module factory is resolved asmyself.DracoDecoderModule || (typeof module !== 'undefined' && module.exports)— the emscripten glue exposes it as a global in a browser worker but onmodule.exports(CommonJS) in a Node eval worker.draco-decoder.js: in Node, spawnnew Worker(code, { eval: true })and listen withworker.on('message', …); the browser keeps the blob-URL path. The message handler normalizesmessage.data ?? message(webMessageEventvs Node raw payload).Notes:
Workerbeing available — consumers shimglobalThis.Worker = require('node:worker_threads').Worker.downloadScript/compileModulestill require http(s)-reachable URLs in Node (local file paths won'tfetch).Verified by decoding
examples/assets/models/heart_draco.glbwith the modified source in both environments (identical output — indices 1080, vertices 12960, stride 24, position + normal): in Node (environment = node) and in the browser (environment = browser).