@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
143 lines (142 loc) • 5.42 kB
JavaScript
;
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;
}