@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
237 lines • 24.3 kB
JavaScript
/* 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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