@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
245 lines • 25.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) {
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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