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
JavaScript
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