threepipe
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

DRACOLoader2.ts 2.9KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import {DRACOLoader} from 'three/examples/jsm/loaders/DRACOLoader.js'
  2. import {BufferGeometry, Color, LoadingManager, Mesh, MeshStandardMaterial} from 'three'
  3. import {AnyOptions} from 'ts-browser-helpers'
  4. import {ILoader} from '../IImporter'
  5. export class DRACOLoader2 extends DRACOLoader implements ILoader<BufferGeometry, Mesh|undefined> {
  6. public encoderPending: Promise<any>|null = null
  7. public encoderConfig: any = {type: 'js'}
  8. public static DRACO_LIBRARY_PATH = 'https://cdn.jsdelivr.net/gh/google/draco@1.4.1/javascript/' // https://github.com/google/draco
  9. // public static DRACO_LIBRARY_PATH = 'https://www.gstatic.com/draco/versioned/decoders/1.4.1/'
  10. // public static DRACO_LIBRARY_PATH = 'https://threejs.org/examples/jsm/libs/draco/'
  11. constructor(manager?: LoadingManager) {
  12. super(manager)
  13. this.setDecoderPath(DRACOLoader2.DRACO_LIBRARY_PATH)
  14. this.setDecoderConfig({type: 'js'}) // todo: hack for now, encoder works with wasm, maybe not decoder.
  15. }
  16. transform(res: BufferGeometry, _: AnyOptions): Mesh|undefined {
  17. if (!res.attributes?.normal) res.computeVertexNormals()
  18. // todo set mesh name from options/path
  19. return res ? new Mesh(res, new MeshStandardMaterial({color: new Color(1, 1, 1)})) : undefined
  20. }
  21. preload(decoder = true, encoder = false): DRACOLoader {
  22. if (decoder) super.preload()
  23. if (encoder) this.initEncoder()
  24. return this
  25. }
  26. public async initEncoder() {
  27. if (this.encoderPending) return this.encoderPending
  28. // this.setDecoderConfig({type: 'js'}) // todo: hack for now.
  29. const useJS = typeof WebAssembly !== 'object' || this.encoderConfig.type === 'js'
  30. const librariesPending = []
  31. if (useJS) {
  32. librariesPending.push(this._loadLibrary('draco_encoder.js', 'text'))
  33. } else {
  34. // todo: not tested
  35. librariesPending.push(this._loadLibrary('draco_wasm_wrapper.js', 'text'))
  36. librariesPending.push(this._loadLibrary('draco_encoder.wasm', 'arraybuffer'))
  37. }
  38. this.encoderPending = Promise.all(librariesPending)
  39. .then((libraries) => {
  40. const jsContent = libraries[ 0 ]
  41. if (!useJS) {
  42. this.encoderConfig.wasmBinary = libraries[ 1 ]
  43. }
  44. const eval2 = eval
  45. return eval2(jsContent + '\nDracoEncoderModule;')?.()
  46. })
  47. return this.encoderPending
  48. }
  49. public async initDecoder() {
  50. await (this as any)._initDecoder()
  51. const jsContent = await fetch((this as any).workerSourceURL).then(async response => response.text()).then(text => {
  52. const i = text.indexOf('/* worker */')
  53. if (i < 1) throw new Error('unable to load decoder module')
  54. return text.substring(0, i - 1)
  55. })
  56. const eval2 = eval
  57. return eval2(jsContent + '\nDracoDecoderModule;')?.()
  58. }
  59. }