UNPKG

mylingo3d

Version:

Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor

133 lines (112 loc) 4.19 kB
import { Box3, BufferAttribute, BufferGeometry } from "three" import { MeshBVH } from "three-mesh-bvh" import code from "./workerString" import { Queue } from "@lincode/promiselikes" const queue = new Queue() export const geometryMeshMap = new WeakMap() type Options = { onProgress?: (progress: number) => void } export class GenerateMeshBVHWorker { private worker: Worker | null public constructor() { const blob = new Blob([code], { type: "application/javascript" }) this.worker = new Worker(URL.createObjectURL(blob)) this.worker.onerror = (e) => { if (e.message) { throw new Error( `GenerateMeshBVHWorker: Could not create Web Worker with error "${e.message}"` ) } else { throw new Error( "GenerateMeshBVHWorker: Could not create Web Worker." ) } } } public async generate(geom: BufferGeometry, options: Options = {}) { await queue if (this.worker === null) { throw new Error("GenerateMeshBVHWorker: Worker has been disposed.") } const { worker } = this const geometry = geom.clone() geometry.dispose() return new Promise<MeshBVH>((resolve, reject) => { worker.onerror = (e) => { reject(new Error(`GenerateMeshBVHWorker: ${e.message}`)) queue.resolve() } worker.onmessage = (e) => { const { data } = e if (data.error) { reject(new Error(data.error)) queue.resolve() 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 ) //@ts-ignore geometry.attributes.position.array = position 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()) } resolve(bvh) queue.resolve() 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 transferrables = [position] if (index) { transferrables.push(index) } worker.postMessage( { index, position, matrixWorld: geometryMeshMap.get(geom).matrixWorld, options: { ...options, onProgress: null, includedProgressCallback: Boolean(options.onProgress), groups: [...geometry.groups] } }, //@ts-ignore transferrables.map((arr) => arr.buffer) ) }) } dispose() { this.worker!.terminate() this.worker = null } terminate() { console.warn( 'GenerateMeshBVHWorker: "terminate" is deprecated. Use "dispose" instead.' ) this.dispose() } }