UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

128 lines (79 loc) 3.32 kB
import { Box3, BufferAttribute } from 'three'; import { MeshBVH } from 'three-mesh-bvh'; // Modified according to https://github.com/gkjohnson/three-mesh-bvh/issues/636#issuecomment-2209571751 import { WorkerBase } from "three-mesh-bvh/src/workers/utils/WorkerBase.js"; export class GenerateMeshBVHWorker extends WorkerBase { constructor() { // TODO: make mesh bvh worker "work" for prebundled CDN loading // https://linear.app/needle/issue/NE-6572 // Also we don't use toplevel imports to not completely fail to load needle-engine where loading the worker fails // const meta_url = import.meta.url; // const getWorker = () => new Worker(url, { type: 'module' }) // console.log(meta_url, url, getWorker()); super(new Worker(new URL('three-mesh-bvh/src/workers/generateMeshBVH.worker.js', import.meta.url), { type: 'module' })); this.name = 'GenerateMeshBVHWorker'; } runTask( worker, geometry, options = {} ) { return new Promise( ( resolve, reject ) => { if ( geometry.getAttribute( 'position' ).isInterleavedBufferAttribute || geometry.index && geometry.index.isInterleavedBufferAttribute ) { throw new Error( 'GenerateMeshBVHWorker: InterleavedBufferAttribute are not supported for the geometry attributes.' ); } worker.onerror = e => { reject(new Error(`[GenerateMeshBVHWorker] ${e.message || "Unknown error. Please check the server console. If you're using vite try adding 'three-mesh-bvh' to 'optimizeDeps.exclude' in your vite.config.js"}`)); }; worker.onmessage = e => { const { data } = e; if ( data.error ) { reject( new Error( data.error ) ); worker.onmessage = null; } else if ( data.serialized ) { const { serialized, position } = data; const bvh = MeshBVH.deserialize( serialized, geometry, { setIndex: false } ); const boundsOptions = Object.assign( { setBoundingBox: true, }, options ); // we need to replace the arrays because they're neutered entirely by the // webworker transfer. geometry.attributes.position.array = position; if ( serialized.index ) { if ( geometry.index ) { geometry.index.array = serialized.index; } else { const newIndex = new BufferAttribute( serialized.index, 1, false ); geometry.setIndex( newIndex ); } } if ( boundsOptions.setBoundingBox ) { geometry.boundingBox = bvh.getBoundingBox( new Box3() ); } if ( options.onProgress ) { options.onProgress( data.progress ); } resolve( bvh ); worker.onmessage = null; } else if ( options.onProgress ) { options.onProgress( data.progress ); } }; const index = geometry.index ? geometry.index.array : null; const position = geometry.attributes.position.array; const transferable = [ position ]; if ( index ) { transferable.push( index ); } worker.postMessage( { index, position, options: { ...options, onProgress: null, includedProgressCallback: Boolean( options.onProgress ), groups: [ ... geometry.groups ], }, }, transferable.map( arr => arr.buffer ).filter( v => ( typeof SharedArrayBuffer === 'undefined' ) || ! ( v instanceof SharedArrayBuffer ) ) ); } ); } }