UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

237 lines 24.3 kB
/* eslint-disable unicorn/prevent-abbreviations */ import { TgdDataset } from "./../../../dataset/index.js"; import { TgdGeometry } from "../../geometry.js"; import { tgdDataMarchingCubesConfigurations, tgdDataMarchingCubesVoxelCorners, tgdDataMarchingCubesVoxelMidPoints, } from "./data.js"; export function tgdMakePointsCloudFromVolume(options, radiusMultiplier = 1) { const helper = new VolumeHelper(options); return helper.getPointsCloud(radiusMultiplier); } export function tgdMakeGeometryFromVolume(options) { const { attPosition = "POSITION" } = options; const helper = new VolumeHelper(options); const { points, elements } = helper.getMesh(); const dataset = new TgdDataset({ [attPosition]: "vec3", }); const smoothingLevel = options.smoothingLevel ?? 0; let position = points; for (let loop = 0; loop < smoothingLevel; loop++) { position = tgdGeometrySmoothVertices(position, elements); } dataset.set(attPosition, position); const geometry = new TgdGeometry({ dataset, attPosition, elements: elements, drawMode: "TRIANGLES", }); geometry.computeNormals(); return geometry; } function tgdGeometrySmoothVertices(positions, elements) { const smoothedPositions = new Float32Array(positions.length); const weights = new Float32Array(positions.length / 3); for (let k = 0; k < elements.length; k += 3) { const aa = elements[k + 0]; const bb = elements[k + 1]; const cc = elements[k + 2]; const a = aa * 3; const b = bb * 3; const c = cc * 3; const xa = positions[a + 0]; const ya = positions[a + 1]; const za = positions[a + 2]; const xb = positions[b + 0]; const yb = positions[b + 1]; const zb = positions[b + 2]; const xc = positions[c + 0]; const yc = positions[c + 1]; const zc = positions[c + 2]; const x = xa + xb + xc; const y = ya + yb + yc; const z = za + zb + zc; smoothedPositions[a + 0] += x; smoothedPositions[a + 1] += y; smoothedPositions[a + 2] += z; smoothedPositions[b + 0] += x; smoothedPositions[b + 1] += y; smoothedPositions[b + 2] += z; smoothedPositions[c + 0] += x; smoothedPositions[c + 1] += y; smoothedPositions[c + 2] += z; weights[aa] += 3; weights[bb] += 3; weights[cc] += 3; } for (let i = 0; i < weights.length; i++) { const w = 1 / weights[i]; const k = i * 3; smoothedPositions[k + 0] *= w; smoothedPositions[k + 1] *= w; smoothedPositions[k + 2] *= w; } return smoothedPositions; } class VolumeHelper { constructor(options) { this.options = options; this._points = []; this._elements = []; this.elementsCount = 0; this._cache = new Map(); this.addTriangles = () => { const { midPoints, options, dimX, dimY, dimZ } = this; const { voxelSize, bboxCorner } = options; const [cornerX, cornerY, cornerZ] = bboxCorner; for (let xi = 0; xi < dimX; xi++) { const x = cornerX + voxelSize * xi; for (let yi = 0; yi < dimY; yi++) { const y = cornerY + voxelSize * yi; for (let zi = 0; zi < dimZ; zi++) { const z = cornerZ + voxelSize * zi; const config = this.configurations[this.getConfigIndex(xi, yi, zi)]; for (let i = 0; i < config.length; i += 3) { const a = config[i + 0]; const b = config[i + 1]; const c = config[i + 2]; const xam = midPoints[a * 3 + 0]; const yam = midPoints[a * 3 + 1]; const zam = midPoints[a * 3 + 2]; const xa = x + xam * voxelSize; const ya = y + yam * voxelSize; const za = z + zam * voxelSize; this.addPointElement(xa, ya, za, key(xi + xam, yi + yam, zi + zam)); const xbm = midPoints[b * 3 + 0]; const ybm = midPoints[b * 3 + 1]; const zbm = midPoints[b * 3 + 2]; const xb = x + xbm * voxelSize; const yb = y + ybm * voxelSize; const zb = z + zbm * voxelSize; this.addPointElement(xb, yb, zb, key(xi + xbm, yi + ybm, zi + zbm)); const xcm = midPoints[c * 3 + 0]; const ycm = midPoints[c * 3 + 1]; const zcm = midPoints[c * 3 + 2]; const xc = x + xcm * voxelSize; const yc = y + ycm * voxelSize; const zc = z + zcm * voxelSize; this.addPointElement(xc, yc, zc, key(xi + xcm, yi + ycm, zi + zcm)); } } } } return { points: new Float32Array(this._points), elements: new Uint32Array(this._elements), }; }; let { voxelSize } = options; if (voxelSize <= 0) { throw new Error(`We cannot do marching cube with voxels so small: ${voxelSize}`); } this.configurations = tgdDataMarchingCubesConfigurations(); this.corners = tgdDataMarchingCubesVoxelCorners(); this.midPoints = tgdDataMarchingCubesVoxelMidPoints(); const { bboxSize } = options; while (true) { this.dimX = Math.ceil(bboxSize[0] / voxelSize); this.dimY = Math.ceil(bboxSize[1] / voxelSize); this.dimZ = Math.ceil(bboxSize[2] / voxelSize); if (this.dimX * this.dimY * this.dimZ < 1e9) break; // Volume is too big, let's double the size of the voxel. voxelSize *= 2; } this.volume = this.computeVolume(); } getMesh() { this.elementsCount = 0; this._cache.clear(); this._points.splice(0); this._elements.splice(0); this.addTriangles(); return { points: new Float32Array(this._points), elements: new Uint32Array(this._elements), }; } getPointsCloud(radiusMultiplier) { const { voxelSize } = this.options; const points = []; this.march((xi, yi, zi, x, y, z) => { if (this.isInside(xi, yi, zi)) { points.push(x, y, z, voxelSize * radiusMultiplier); } }); return new Float32Array(points); } addPointElement(x, y, z, k) { const cache = this._cache.get(k); if (typeof cache === "number") { this._elements.push(cache); } else { this._points.push(x, y, z); const elem = this.elementsCount++; this._cache.set(k, elem); this._elements.push(elem); } } getConfigIndex(xi, yi, zi) { const { corners } = this; let configIndex = 0; let bit = 1; for (let i = 0; i < corners.length; i += 3) { const vx = corners[i + 0]; const vy = corners[i + 1]; const vz = corners[i + 2]; if (this.isInside(xi + vx, yi + vy, zi + vz)) { configIndex += bit; } bit <<= 1; } return configIndex; } march(func) { const { dimX, dimY, dimZ, options } = this; const { voxelSize, bboxCorner } = options; const [cornerX, cornerY, cornerZ] = bboxCorner; for (let xi = 0; xi < dimX; xi++) { const x = cornerX + voxelSize * xi; for (let yi = 0; yi < dimY; yi++) { const y = cornerY + voxelSize * yi; for (let zi = 0; zi < dimZ; zi++) { const z = cornerZ + voxelSize * zi; func(xi, yi, zi, x, y, z); } } } } isInside(xi, yi, zi) { const { dimY, dimZ } = this; const index = zi + yi * (dimZ + 1) + xi * (dimZ + 1) * (dimY + 1); return this.volume[index] === 1; } computeVolume() { const { bboxCorner, voxelSize, sdfPoint } = this.options; const { dimX, dimY, dimZ } = this; const [cornerX, cornerY, cornerZ] = bboxCorner; const volume = new Uint8Array((dimX + 1) * (dimY + 1) * (dimZ + 1)); let index = 0; for (let xi = 0; xi <= dimX; xi++) { const x = cornerX + voxelSize * xi; for (let yi = 0; yi <= dimY; yi++) { const y = cornerY + voxelSize * yi; for (let zi = 0; zi <= dimZ; zi++) { const z = cornerZ + voxelSize * zi; const distance = sdfPoint(x, y, z); volume[index++] = distance < 0 ? 1 : 0; } } } return volume; } } function key(x, y, z) { return `${(x + x).toFixed(0)}/${(y + y).toFixed(0)}/${(z + z).toFixed(0)}`; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFyY2hpbmctY3ViZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZ2VvbWV0cnkvdG9vbHMvbWFyY2hpbmctY3ViZXMvbWFyY2hpbmctY3ViZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsa0RBQWtEO0FBQ2xELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFHekMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBQzVDLE9BQU8sRUFDSCxrQ0FBa0MsRUFDbEMsZ0NBQWdDLEVBQ2hDLGtDQUFrQyxHQUNyQyxNQUFNLFFBQVEsQ0FBQTtBQTBCZixNQUFNLFVBQVUsNEJBQTRCLENBQUMsT0FBc0MsRUFBRSxnQkFBZ0IsR0FBRyxDQUFDO0lBQ3JHLE1BQU0sTUFBTSxHQUFHLElBQUksWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ3hDLE9BQU8sTUFBTSxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFBO0FBQ2xELENBQUM7QUFFRCxNQUFNLFVBQVUseUJBQXlCLENBQUMsT0FBc0M7SUFDNUUsTUFBTSxFQUFFLFdBQVcsR0FBRyxVQUFVLEVBQUUsR0FBRyxPQUFPLENBQUE7SUFDNUMsTUFBTSxNQUFNLEdBQUcsSUFBSSxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDeEMsTUFBTSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUE7SUFDN0MsTUFBTSxPQUFPLEdBQUcsSUFBSSxVQUFVLENBQUM7UUFDM0IsQ0FBQyxXQUFXLENBQUMsRUFBRSxNQUFNO0tBQ3hCLENBQUMsQ0FBQTtJQUNGLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxjQUFjLElBQUksQ0FBQyxDQUFBO0lBQ2xELElBQUksUUFBUSxHQUFpQixNQUFNLENBQUE7SUFDbkMsS0FBSyxJQUFJLElBQUksR0FBRyxDQUFDLEVBQUUsSUFBSSxHQUFHLGNBQWMsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQy9DLFFBQVEsR0FBRyx5QkFBeUIsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUE7SUFDNUQsQ0FBQztJQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLFFBQVEsQ0FBQyxDQUFBO0lBQ2xDLE1BQU0sUUFBUSxHQUFHLElBQUksV0FBVyxDQUFDO1FBQzdCLE9BQU87UUFDUCxXQUFXO1FBQ1gsUUFBUSxFQUFFLFFBQVE7UUFDbEIsUUFBUSxFQUFFLFdBQVc7S0FDeEIsQ0FBQyxDQUFBO0lBQ0YsUUFBUSxDQUFDLGNBQWMsRUFBRSxDQUFBO0lBQ3pCLE9BQU8sUUFBUSxDQUFBO0FBQ25CLENBQUM7QUFFRCxTQUFTLHlCQUF5QixDQUFDLFNBQXVCLEVBQUUsUUFBaUM7SUFDekYsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLFlBQVksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDNUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxZQUFZLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtJQUN0RCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDMUMsTUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUMxQixNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQzFCLE1BQU0sRUFBRSxHQUFHLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDMUIsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQTtRQUNoQixNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFBO1FBQ2hCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUE7UUFDaEIsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUMzQixNQUFNLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQzNCLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDM0IsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUMzQixNQUFNLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQzNCLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDM0IsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUMzQixNQUFNLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQzNCLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDM0IsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUE7UUFDdEIsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUE7UUFDdEIsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUE7UUFDdEIsaUJBQWlCLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUM3QixpQkFBaUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQzdCLGlCQUFpQixDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDN0IsaUJBQWlCLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUM3QixpQkFBaUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFBO1FB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QUcsQ0FBQyxDQUFDLENBQUE7NEJBQ3ZCLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7NEJBQ3ZCLE1BQU0sR0FBRyxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBOzRCQUNoQyxNQUFNLEdBQUcsR0FBRyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTs0QkFDaEMsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7NEJBQ2hDLE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsU0FBUyxDQUFBOzRCQUM5QixNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLFNBQVMsQ0FBQTs0QkFDOUIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxHQUFHLEdBQUcsR0FBRyxTQUFTLENBQUE7NEJBQzlCLElBQUksQ0FBQyxlQUFlLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLEVBQUUsRUFBRSxHQUFHLEdBQUcsRUFBRSxFQUFFLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQTs0QkFDbkUsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7NEJBQ2hDLE1BQU0sR0FBRyxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBOzRCQUNoQyxNQUFNLEdBQUcsR0FBRyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTs0QkFDaEMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxHQUFHLEdBQUcsR0FBRyxTQUFTLENBQUE7NEJBQzlCLE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsU0FBUyxDQUFBOzRCQUM5QixNQUFNLEVBQUUsR0FBRyxDQUFD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