1 line
6.8 KiB
Plaintext
1 line
6.8 KiB
Plaintext
|
|
{"version":3,"file":"LUT3dlLoader.cjs","sources":["../../src/loaders/LUT3dlLoader.js"],"sourcesContent":["// http://download.autodesk.com/us/systemdocs/help/2011/lustre/index.html?url=./files/WSc4e151a45a3b785a24c3d9a411df9298473-7ffd.htm,topicNumber=d0e9492\n// https://community.foundry.com/discuss/topic/103636/format-spec-for-3dl?mode=Post&postID=895258\nimport { Loader, FileLoader, DataTexture, RGBAFormat, UnsignedByteType, ClampToEdgeWrapping, LinearFilter } from 'three'\nimport { Data3DTexture } from '../_polyfill/Data3DTexture'\n\nexport class LUT3dlLoader extends Loader {\n load(url, onLoad, onProgress, onError) {\n const loader = new FileLoader(this.manager)\n loader.setPath(this.path)\n loader.setResponseType('text')\n loader.load(\n url,\n (text) => {\n try {\n onLoad(this.parse(text))\n } catch (e) {\n if (onError) {\n onError(e)\n } else {\n console.error(e)\n }\n\n this.manager.itemError(url)\n }\n },\n onProgress,\n onError,\n )\n }\n\n parse(str) {\n // remove empty lines and comment lints\n str = str\n .replace(/^#.*?(\\n|\\r)/gm, '')\n .replace(/^\\s*?(\\n|\\r)/gm, '')\n .trim()\n\n const lines = str.split(/[\\n\\r]+/g)\n\n // first line is the positions on the grid that are provided by the LUT\n const gridLines = lines[0]\n .trim()\n .split(/\\s+/g)\n .map((e) => parseFloat(e))\n const gridStep = gridLines[1] - gridLines[0]\n const size = gridLines.length\n\n for (let i = 1, l = gridLines.length; i < l; i++) {\n if (gridStep !== gridLines[i] - gridLines[i - 1]) {\n throw new Error('LUT3dlLoader: Inconsistent grid size not supported.')\n }\n }\n\n const dataArray = new Array(size * size * size * 4)\n let index = 0\n let maxOutputValue = 0.0\n for (let i = 1, l = lines.length; i < l; i++) {\n const line = lines[i].trim()\n const split = line.split(/\\s/g)\n\n const r = parseFloat(split[0])\n const g = parseFloat(split[1])\n const b = parseFloat(split[2])\n maxOutputValue = Math.max(maxOutputValue, r, g, b)\n\n const bLayer = index % size\n const gLayer = Math.floor(index / size) % size\n const rLayer = Math.floor(index / (size * size)) % size\n\n // b grows first, then g, then r\n const pixelIndex = bLayer * size * size + gLayer * size + rLayer\n dataArray[4 * pixelIndex + 0] = r\n dataArray[4 * pixelIndex + 1] = g\n dataArray[4 * pixelIndex + 2] = b\n dataArray[4 * pixelIndex + 3] = 1.0\n index += 1\n }\n\n // Find the apparent bit depth of the stored RGB values and map the\n // values to [ 0, 255 ].\n const bits = Math.ceil(Math.log2(maxOutputValue))\n const maxBitValue = Math.pow(2.0, bits)\n for (let i = 0, l = dataArray.length; i < l; i += 4) {\n const r = dataArray[i + 0]\n const g = dataArray[i + 1]\n const b = dataArray[i + 2]\n dataArray[i + 0] = (255 * r) / maxBitValue // r\n dataArray[i + 1] = (255 * g) / maxBitValue // g\n dataArray[i + 2] = (255 * b) / maxBitValue // b\n }\n\n const data = new Uint8Array(dataArray)\n const texture = new DataTexture()\n texture.image.data = data\n texture.image.width = size\n texture.image.height = size * size\n texture.format = RGBAFormat\n texture.type = UnsignedByteType\n texture.magFilter = LinearFilter\n texture.minFilter = LinearFilter\n texture.wrapS = ClampToEdgeWrapping\n texture.wrapT = ClampToEdgeWrapping\n texture.generateMipmaps = false\n texture.needsUpdate = true\n\n const texture3D = new Data3DTexture()\n texture3D.image.data = data\n texture3D.image.width = size\n texture3D.image.height = size\n texture3D.image.depth = size\n texture3D.format = RGBAFormat\n texture3D.type = UnsignedByteType\n texture3D.magFilter = LinearFilter\n texture3D.minFilter = LinearFilter\n texture3D.wrapS = ClampToEdgeWrapping\n texture3D.wrapT = ClampToE
|