UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

143 lines (142 loc) 5.42 kB
"use strict"; import { Data3DTexture, RedFormat, LinearFilter, HalfFloatType, FloatType, ClampToEdgeWrapping } from "three"; import { CoreBaseLoader } from "../_Base"; import { CoreUserAgent } from "../../UserAgent"; export class SDFLoader extends CoreBaseLoader { constructor(url, _node) { super(url, _node); this._node = _node; } async load(successCallback, progressCallback, errorCallback) { const url = this._urlToLoad(); try { const response = await fetch(url); const blob = await response.blob(); var fileReader = new FileReader(); fileReader.onload = function(event) { var _a; try { const arrayBuffer = (_a = event.target) == null ? void 0 : _a.result; if (arrayBuffer && arrayBuffer instanceof ArrayBuffer) { const texture = loadSDFMetadata(arrayBuffer); successCallback(texture); } else { errorCallback(new ErrorEvent("content is not an arrayBuffer")); } } catch (err) { errorCallback(err instanceof ErrorEvent ? err : new ErrorEvent("fail to read SDF file")); } }; fileReader.onerror = () => { errorCallback(new ErrorEvent("failure to read response content")); }; fileReader.readAsArrayBuffer(blob); } catch (err) { errorCallback(err); } } } export function addSDFMetadataToContainer(texture, options) { const dataContainer = texture == null ? void 0 : texture.image; if (!dataContainer) { throw new Error("the input must be a 3D texture"); return; } dataContainer.boundMinx = options.boundMin.x; dataContainer.boundMiny = options.boundMin.y; dataContainer.boundMinz = options.boundMin.z; dataContainer.boundMaxx = options.boundMax.x; dataContainer.boundMaxy = options.boundMax.y; dataContainer.boundMaxz = options.boundMax.z; dataContainer.resolutionx = options.resolution.x; dataContainer.resolutiony = options.resolution.y; dataContainer.resolutionz = options.resolution.z; } export function readSDFMetadataFromContainer(texture) { const dataContainer = texture == null ? void 0 : texture.image; if (!dataContainer) { throw new Error("the input must be a 3D texture"); return; } return dataContainer; } export function saveSDFMetadata(texture) { const dataContainer = readSDFMetadataFromContainer(texture); if (!dataContainer) { throw new Error("the input must be a 3D texture"); return; } const data = dataContainer.data; const metadataSizes = { metadataLength: 1, dimensions: 3, bounds: 6, resolution: 3 }; const metadataLength = metadataSizes.metadataLength + metadataSizes.dimensions + metadataSizes.bounds + metadataSizes.resolution; const currentLength = data.length; const dataWithMetadata = new Float32Array(currentLength + metadataLength); dataWithMetadata[0] = metadataLength; dataWithMetadata[1] = dataContainer.width; dataWithMetadata[2] = dataContainer.height; dataWithMetadata[3] = dataContainer.depth; dataWithMetadata[4] = dataContainer.boundMinx; dataWithMetadata[5] = dataContainer.boundMiny; dataWithMetadata[6] = dataContainer.boundMinz; dataWithMetadata[7] = dataContainer.boundMaxx; dataWithMetadata[8] = dataContainer.boundMaxy; dataWithMetadata[9] = dataContainer.boundMaxz; dataWithMetadata[10] = dataContainer.resolutionx; dataWithMetadata[11] = dataContainer.resolutiony; dataWithMetadata[12] = dataContainer.resolutionz; for (let i = 0; i < currentLength; i++) { dataWithMetadata[i + metadataLength] = data[i]; } return dataWithMetadata; } function loadSDFMetadata(arrayBuffer) { const float32Array = new Float32Array(arrayBuffer); const currentLength = float32Array.length; const metadataLength = float32Array[0]; const width = float32Array[1]; const height = float32Array[2]; const depth = float32Array[3]; const boundMinx = float32Array[4]; const boundMiny = float32Array[5]; const boundMinz = float32Array[6]; const boundMaxx = float32Array[7]; const boundMaxy = float32Array[8]; const boundMaxz = float32Array[9]; const resolutionx = float32Array[10]; const resolutiony = float32Array[11]; const resolutionz = float32Array[12]; const texture = createSDFTexture(width, height, depth); const dataWithoutMetadata = texture.image.data; for (let i = 0; i < currentLength; i++) { dataWithoutMetadata[i] = float32Array[i + metadataLength]; } const dataContainer = texture.image; dataContainer.boundMinx = boundMinx; dataContainer.boundMiny = boundMiny; dataContainer.boundMinz = boundMinz; dataContainer.boundMaxx = boundMaxx; dataContainer.boundMaxy = boundMaxy; dataContainer.boundMaxz = boundMaxz; dataContainer.resolutionx = resolutionx; dataContainer.resolutiony = resolutiony; dataContainer.resolutionz = resolutionz; return texture; } export function createSDFTexture(width, height, depth) { const texture = new Data3DTexture(new Float32Array(width * height * depth).fill(0), width, height, depth); texture.format = RedFormat; texture.minFilter = LinearFilter; texture.magFilter = LinearFilter; texture.wrapS = ClampToEdgeWrapping; texture.wrapT = ClampToEdgeWrapping; texture.wrapR = ClampToEdgeWrapping; texture.unpackAlignment = 1; texture.needsUpdate = true; texture.type = CoreUserAgent.isiOS() ? HalfFloatType : FloatType; return texture; }