UNPKG

three-stdlib

Version:

stand-alone library of threejs examples

434 lines (433 loc) 10.2 kB
import { Loader, FileLoader, Mesh, BufferGeometry, Float32BufferAttribute, MeshStandardMaterial, RedFormat, NearestFilter, LinearFilter } from "three"; import { Data3DTexture } from "../_polyfill/Data3DTexture.js"; class VOXLoader extends Loader { load(url, onLoad, onProgress, onError) { const scope = this; const loader = new FileLoader(scope.manager); loader.setPath(scope.path); loader.setResponseType("arraybuffer"); loader.setRequestHeader(scope.requestHeader); loader.load( url, function(buffer) { try { onLoad(scope.parse(buffer)); } catch (e) { if (onError) { onError(e); } else { console.error(e); } scope.manager.itemError(url); } }, onProgress, onError ); } parse(buffer) { const data = new DataView(buffer); const id = data.getUint32(0, true); const version = data.getUint32(4, true); if (id !== 542658390 || version !== 150) { console.error("Not a valid VOX file"); return; } const DEFAULT_PALETTE = [ 0, 4294967295, 4291624959, 4288282623, 4284940287, 4281597951, 4278255615, 4294954239, 4291611903, 4288269567, 4284927231, 4281584895, 4278242559, 4294941183, 4291598847, 4288256511, 4284914175, 4281571839, 4278229503, 4294928127, 4291585791, 4288243455, 4284901119, 4281558783, 4278216447, 4294915071, 4291572735, 4288230399, 4284888063, 4281545727, 4278203391, 4294902015, 4291559679, 4288217343, 4284875007, 4281532671, 4278190335, 4294967244, 4291624908, 4288282572, 4284940236, 4281597900, 4278255564, 4294954188, 4291611852, 4288269516, 4284927180, 4281584844, 4278242508, 4294941132, 4291598796, 4288256460, 4284914124, 4281571788, 4278229452, 4294928076, 4291585740, 4288243404, 4284901068, 4281558732, 4278216396, 4294915020, 4291572684, 4288230348, 4284888012, 4281545676, 4278203340, 4294901964, 4291559628, 4288217292, 4284874956, 4281532620, 4278190284, 4294967193, 4291624857, 4288282521, 4284940185, 4281597849, 4278255513, 4294954137, 4291611801, 4288269465, 4284927129, 4281584793, 4278242457, 4294941081, 4291598745, 4288256409, 4284914073, 4281571737, 4278229401, 4294928025, 4291585689, 4288243353, 4284901017, 4281558681, 4278216345, 4294914969, 4291572633, 4288230297, 4284887961, 4281545625, 4278203289, 4294901913, 4291559577, 4288217241, 4284874905, 4281532569, 4278190233, 4294967142, 4291624806, 4288282470, 4284940134, 4281597798, 4278255462, 4294954086, 4291611750, 4288269414, 4284927078, 4281584742, 4278242406, 4294941030, 4291598694, 4288256358, 4284914022, 4281571686, 4278229350, 4294927974, 4291585638, 4288243302, 4284900966, 4281558630, 4278216294, 4294914918, 4291572582, 4288230246, 4284887910, 4281545574, 4278203238, 4294901862, 4291559526, 4288217190, 4284874854, 4281532518, 4278190182, 4294967091, 4291624755, 4288282419, 4284940083, 4281597747, 4278255411, 4294954035, 4291611699, 4288269363, 4284927027, 4281584691, 4278242355, 4294940979, 4291598643, 4288256307, 4284913971, 4281571635, 4278229299, 4294927923, 4291585587, 4288243251, 4284900915, 4281558579, 4278216243, 4294914867, 4291572531, 4288230195, 4284887859, 4281545523, 4278203187, 4294901811, 4291559475, 4288217139, 4284874803, 4281532467, 4278190131, 4294967040, 4291624704, 4288282368, 4284940032, 4281597696, 4278255360, 4294953984, 4291611648, 4288269312, 4284926976, 4281584640, 4278242304, 4294940928, 4291598592, 4288256256, 4284913920, 4281571584, 4278229248, 4294927872, 4291585536, 4288243200, 4284900864, 4281558528, 4278216192, 4294914816, 4291572480, 4288230144, 4284887808, 4281545472, 4278203136, 4294901760, 4291559424, 4288217088, 4284874752, 4281532416, 4278190318, 4278190301, 4278190267, 4278190250, 4278190216, 4278190199, 4278190165, 4278190148, 4278190114, 4278190097, 4278251008, 4278246656, 4278237952, 4278233600, 4278224896, 4278220544, 4278211840, 4278207488, 4278198784, 4278194432, 4293787648, 4292673536, 4290445312, 4289331200, 4287102976, 4285988864, 4283760640, 4282646528, 4280418304, 4279304192, 4293848814, 4292730333, 4290493371, 4289374890, 4287137928, 4286019447, 4283782485, 4282664004, 4280427042, 4279308561 ]; let i = 8; let chunk; const chunks = []; while (i < data.byteLength) { let id2 = ""; for (let j = 0; j < 4; j++) { id2 += String.fromCharCode(data.getUint8(i++)); } const chunkSize = data.getUint32(i, true); i += 4; i += 4; if (id2 === "SIZE") { const x = data.getUint32(i, true); i += 4; const y = data.getUint32(i, true); i += 4; const z = data.getUint32(i, true); i += 4; chunk = { palette: DEFAULT_PALETTE, size: { x, y, z } }; chunks.push(chunk); i += chunkSize - 3 * 4; } else if (id2 === "XYZI") { const numVoxels = data.getUint32(i, true); i += 4; chunk.data = new Uint8Array(buffer, i, numVoxels * 4); i += numVoxels * 4; } else if (id2 === "RGBA") { const palette = [0]; for (let j = 0; j < 256; j++) { palette[j + 1] = data.getUint32(i, true); i += 4; } chunk.palette = palette; } else { i += chunkSize; } } return chunks; } } class VOXMesh extends Mesh { constructor(chunk) { const data = chunk.data; const size = chunk.size; const palette = chunk.palette; const vertices = []; const colors = []; const nx = [0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1]; const px = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0]; const py = [0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1]; const ny = [0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0]; const nz = [0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0]; const pz = [0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1]; function add(tile, x, y, z, r, g, b) { x -= size.x / 2; y -= size.z / 2; z += size.y / 2; for (let i = 0; i < 18; i += 3) { vertices.push(tile[i + 0] + x, tile[i + 1] + y, tile[i + 2] + z); colors.push(r, g, b); } } const offsety = size.x; const offsetz = size.x * size.y; const array = new Uint8Array(size.x * size.y * size.z); for (let j = 0; j < data.length; j += 4) { const x = data[j + 0]; const y = data[j + 1]; const z = data[j + 2]; const index = x + y * offsety + z * offsetz; array[index] = 255; } let hasColors = false; for (let j = 0; j < data.length; j += 4) { const x = data[j + 0]; const y = data[j + 1]; const z = data[j + 2]; const c = data[j + 3]; const hex = palette[c]; const r = (hex >> 0 & 255) / 255; const g = (hex >> 8 & 255) / 255; const b = (hex >> 16 & 255) / 255; if (r > 0 || g > 0 || b > 0) hasColors = true; const index = x + y * offsety + z * offsetz; if (array[index + 1] === 0 || x === size.x - 1) add(px, x, z, -y, r, g, b); if (array[index - 1] === 0 || x === 0) add(nx, x, z, -y, r, g, b); if (array[index + offsety] === 0 || y === size.y - 1) add(ny, x, z, -y, r, g, b); if (array[index - offsety] === 0 || y === 0) add(py, x, z, -y, r, g, b); if (array[index + offsetz] === 0 || z === size.z - 1) add(pz, x, z, -y, r, g, b); if (array[index - offsetz] === 0 || z === 0) add(nz, x, z, -y, r, g, b); } const geometry = new BufferGeometry(); geometry.setAttribute("position", new Float32BufferAttribute(vertices, 3)); geometry.computeVertexNormals(); const material = new MeshStandardMaterial(); if (hasColors) { geometry.setAttribute("color", new Float32BufferAttribute(colors, 3)); material.vertexColors = true; } super(geometry, material); } } class VOXData3DTexture extends Data3DTexture { constructor(chunk) { const data = chunk.data; const size = chunk.size; const offsety = size.x; const offsetz = size.x * size.y; const array = new Uint8Array(size.x * size.y * size.z); for (let j = 0; j < data.length; j += 4) { const x = data[j + 0]; const y = data[j + 1]; const z = data[j + 2]; const index = x + y * offsety + z * offsetz; array[index] = 255; } super(array, size.x, size.y, size.z); this.format = RedFormat; this.minFilter = NearestFilter; this.magFilter = LinearFilter; this.unpackAlignment = 1; this.needsUpdate = true; } } export { VOXData3DTexture, VOXLoader, VOXMesh }; //# sourceMappingURL=VOXLoader.js.map