UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

245 lines 25.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) { var _a; const { attPosition = "POSITION" } = options; const helper = new VolumeHelper(options); const { points, elements } = helper.getMesh(); const dataset = new TgdDataset({ [attPosition]: "vec3", }); const smoothingLevel = (_a = options.smoothingLevel) !== null && _a !== void 0 ? _a : 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}`); } const time0 = Date.now(); 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(); console.log("Volume: ", Date.now() - time0, "ms"); } getMesh() { const time0 = Date.now(); this.elementsCount = 0; this._cache.clear(); this._points.splice(0); this._elements.splice(0); this.addTriangles(); console.log("Triangles: ", Date.now() - time0, "ms"); return { points: new Float32Array(this._points), elements: new Uint32Array(this._elements), }; } getPointsCloud(radiusMultiplier) { const time0 = Date.now(); 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); } }); console.log("PontsCould: ", Date.now() - time0, "ms"); 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) { console.log("------------------------------------------------------"); 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFyY2hpbmctY3ViZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZ2VvbWV0cnkvdG9vbHMvbWFyY2hpbmctY3ViZXMvbWFyY2hpbmctY3ViZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsa0RBQWtEO0FBQ2xELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFFekMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBRTVDLE9BQU8sRUFDSCxrQ0FBa0MsRUFDbEMsZ0NBQWdDLEVBQ2hDLGtDQUFrQyxHQUNyQyxNQUFNLFFBQVEsQ0FBQTtBQTBCZixNQUFNLFVBQVUsNEJBQTRCLENBQ3hDLE9BQXNDLEVBQ3RDLGdCQUFnQixHQUFHLENBQUM7SUFFcEIsTUFBTSxNQUFNLEdBQUcsSUFBSSxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDeEMsT0FBTyxNQUFNLENBQUMsY0FBYyxDQUFDLGdCQUFnQixDQUFDLENBQUE7QUFDbEQsQ0FBQztBQUVELE1BQU0sVUFBVSx5QkFBeUIsQ0FDckMsT0FBc0M7O0lBRXRDLE1BQU0sRUFBRSxXQUFXLEdBQUcsVUFBVSxFQUFFLEdBQUcsT0FBTyxDQUFBO0lBQzVDLE1BQU0sTUFBTSxHQUFHLElBQUksWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ3hDLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFBO0lBQzdDLE1BQU0sT0FBTyxHQUFHLElBQUksVUFBVSxDQUFDO1FBQzNCLENBQUMsV0FBVyxDQUFDLEVBQUUsTUFBTTtLQUN4QixDQUFDLENBQUE7SUFDRixNQUFNLGNBQWMsR0FBRyxNQUFBLE9BQU8sQ0FBQyxjQUFjLG1DQUFJLENBQUMsQ0FBQTtJQUNsRCxJQUFJLFFBQVEsR0FBaUIsTUFBTSxDQUFBO0lBQ25DLEtBQUssSUFBSSxJQUFJLEdBQUcsQ0FBQyxFQUFFLElBQUksR0FBRyxjQUFjLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQztRQUMvQyxRQUFRLEdBQUcseUJBQXlCLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFBO0lBQzVELENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQTtJQUNsQyxNQUFNLFFBQVEsR0FBRyxJQUFJLFdBQVcsQ0FBQztRQUM3QixPQUFPO1FBQ1AsV0FBVztRQUNYLFFBQVEsRUFBRSxRQUFRO1FBQ2xCLFFBQVEsRUFBRSxXQUFXO0tBQ3hCLENBQUMsQ0FBQTtJQUNGLFFBQVEsQ0FBQyxjQUFjLEVBQUUsQ0FBQTtJQUN6QixPQUFPLFFBQVEsQ0FBQTtBQUNuQixDQUFDO0FBRUQsU0FBUyx5QkFBeUIsQ0FDOUIsU0FBdUIsRUFDdkIsUUFBaUM7SUFFakMsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLFlBQVksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDNUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxZQUFZLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtJQUN0RCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDMUMsTUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUMxQixNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQzFCLE1BQU0sRUFBRSxHQUFHLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDMUIsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQTtRQUNoQixNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFBO1FBQ2hCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUE7UUFDaEIsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUMzQixNQUFNLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQzNCLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDM0IsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUMzQixNQUFNLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQzNCLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDM0IsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUMzQixNQUFNLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQzNCLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDM0IsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUE7UUFDdEIsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUE7UUFDdEIsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUE7UUFDdEIsaUJBQWlCLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUM3QixpQkFBaUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQzdCLGlCQUFpQixDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDN0IsaUJBQWlCLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUM3QixpQkFBaUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUks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