UNPKG

@pnext/three-loader

Version:

Potree loader for ThreeJS, converted and adapted to Typescript.

154 lines (125 loc) 4.02 kB
/* global onmessage:true postMessage:false Module */ /* exported onmessage */ // laz-loader-worker.js // // importScripts('laz-perf.js'); let instance = null; // laz-perf instance function readAs(buf, Type, offset, count) { count = count === undefined || count === 0 ? 1 : count; let sub = buf.slice(offset, offset + Type.BYTES_PER_ELEMENT * count); let r = new Type(sub); if (count === undefined || count === 1) { return r[0]; } let ret = []; for (let i = 0; i < count; i++) { ret.push(r[i]); } return ret; } function parseLASHeader(arraybuffer) { let o = {}; o.pointsOffset = readAs(arraybuffer, Uint32Array, 32 * 3); o.pointsFormatId = readAs(arraybuffer, Uint8Array, 32 * 3 + 8); o.pointsStructSize = readAs(arraybuffer, Uint16Array, 32 * 3 + 8 + 1); o.pointsCount = readAs(arraybuffer, Uint32Array, 32 * 3 + 11); let start = 32 * 3 + 35; o.scale = readAs(arraybuffer, Float64Array, start, 3); start += 24; // 8*3 o.offset = readAs(arraybuffer, Float64Array, start, 3); start += 24; let bounds = readAs(arraybuffer, Float64Array, start, 6); start += 48; // 8*6; o.maxs = [bounds[0], bounds[2], bounds[4]]; o.mins = [bounds[1], bounds[3], bounds[5]]; return o; } function handleEvent(msg) { switch (msg.type) { case 'open': try { instance = new Module.LASZip(); let abInt = new Uint8Array(msg.arraybuffer); let buf = Module._malloc(msg.arraybuffer.byteLength); instance.arraybuffer = msg.arraybuffer; instance.buf = buf; Module.HEAPU8.set(abInt, buf); instance.open(buf, msg.arraybuffer.byteLength); instance.readOffset = 0; postMessage({ type: 'open', status: 1 }); } catch (e) { postMessage({ type: 'open', status: 0, details: e }); } break; case 'header': if (!instance) { if (PRODUCTION) { throw new Error(); } else { throw new Error('You need to open the file before trying to read header'); } } let header = parseLASHeader(instance.arraybuffer); header.pointsFormatId &= 0x3f; instance.header = header; postMessage({ type: 'header', status: 1, header: header }); break; case 'read': if (!instance) { if (PRODUCTION) { throw new Error(); } else { throw new Error('You need to open the file before trying to read stuff'); } } // msg.start let count = msg.count; let skip = msg.skip; let o = instance; if (!o.header) { if (PRODUCTION) { throw new Error(); } else { throw new Error( 'You need to query header before reading, I maintain state that way, sorry :(', ); } } let pointsToRead = Math.min(count * skip, o.header.pointsCount - o.readOffset); let bufferSize = Math.ceil(pointsToRead / skip); let pointsRead = 0; let thisBuf = new Uint8Array(bufferSize * o.header.pointsStructSize); let bufRead = Module._malloc(o.header.pointsStructSize); for (let i = 0; i < pointsToRead; i++) { o.getPoint(bufRead); if (i % skip === 0) { let a = new Uint8Array(Module.HEAPU8.buffer, bufRead, o.header.pointsStructSize); thisBuf.set(a, pointsRead * o.header.pointsStructSize, o.header.pointsStructSize); pointsRead++; } o.readOffset++; } postMessage({ type: 'header', status: 1, buffer: thisBuf.buffer, count: pointsRead, hasMoreData: o.readOffset < o.header.pointsCount, }); break; case 'close': if (instance !== null) { instance.delete(); instance = null; } postMessage({ type: 'close', status: 1 }); break; } } onmessage = function (event) { try { handleEvent(event.data); } catch (e) { postMessage({ type: event.data.type, status: 0, details: e }); } };