UNPKG

threepipe

Version:

A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.

92 lines 4.05 kB
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'; import { Color, Mesh } from 'three'; import { PhysicalMaterial } from '../../core'; export class DRACOLoader2 extends DRACOLoader { // public static DRACO_LIBRARY_PATH = 'https://www.gstatic.com/draco/versioned/decoders/1.4.1/' // public static DRACO_LIBRARY_PATH = 'https://threejs.org/examples/jsm/libs/draco/' constructor(manager) { super(manager); this.encoderPending = null; this.encoderConfig = { type: 'js' }; this.setDecoderPath(DRACOLoader2.DRACO_LIBRARY_PATH); this.setDecoderConfig({ type: 'js' }); // todo: hack for now, encoder works with wasm, maybe not decoder. } transform(res, _) { if (!res.attributes?.normal) res.computeVertexNormals(); // todo set mesh name from options/path return res ? new Mesh(res, new PhysicalMaterial({ color: new Color(1, 1, 1) })) : undefined; } preload(decoder = true, encoder = false) { if (decoder) super.preload(); if (encoder) this.initEncoder(); return this; } async initEncoder() { if (this.encoderPending) return this.encoderPending; // this.setDecoderConfig({type: 'js'}) // todo: hack for now. const useJS = typeof WebAssembly !== 'object' || this.encoderConfig.type === 'js'; const librariesPending = []; if (useJS) { librariesPending.push(this._loadLibrary('draco_encoder.js', 'text')); } else { // todo: not tested librariesPending.push(this._loadLibrary('draco_wasm_wrapper.js', 'text')); librariesPending.push(this._loadLibrary('draco_encoder.wasm', 'arraybuffer')); } this.encoderPending = Promise.all(librariesPending) .then((libraries) => { const jsContent = libraries[0]; if (!useJS) { this.encoderConfig.wasmBinary = libraries[1]; } const eval2 = eval; return eval2(jsContent + '\nDracoEncoderModule;')?.(); }); return this.encoderPending; } async initDecoder() { await this._initDecoder(); const jsContent = await fetch(this.workerSourceURL).then(async (response) => response.text()).then(text => { const i = text.indexOf('/* worker */'); if (i < 1) throw new Error('unable to load decoder module'); return text.substring(0, i - 1); }); const eval2 = eval; return eval2(jsContent + '\nDracoDecoderModule;')?.(); } // eslint-disable-next-line @typescript-eslint/naming-convention async _loadLibrary(url, responseType) { if (DRACOLoader2.LibraryValueMap[url]) return DRACOLoader2.LibraryValueMap[url]; return DRACOLoader2.LibraryValueMap[url] = await super._loadLibrary(url, responseType); } /** * Set the decoder js string * Sample for how to set LibraryValueMap * This is useful for bundling the draco decoder js file with your app source * @example * First put the draco_decoder.js file in your src folder, then import it in js/ts as a string * ```js * import draco_decoder from './libs/draco_decoder.1.5.6.js?raw' // vite will load this as a string * // console.log(draco_decoder) // this should be a string with js content * DRACOLoader2.SetDecoderJsString(draco_decoder) * ``` * @param jsString - the contents of draco_decoder.js file */ static SetDecoderJsString(jsString) { this.LibraryValueMap['draco_decoder.js'] = jsString; } } DRACOLoader2.DRACO_LIBRARY_PATH = 'https://cdn.jsdelivr.net/gh/google/draco@1.5.6/javascript/'; // https://github.com/google/draco /** * This is a hack to allow bundling the draco decoder js file with your app source * See {@link DRACOLoader2.SetDecoderJsString} for example */ DRACOLoader2.LibraryValueMap = {}; //# sourceMappingURL=DRACOLoader2.js.map