feat: face separation

This commit is contained in:
2024-03-03 14:24:49 +01:00
parent 805ec392aa
commit 2007df86c9
2 changed files with 55 additions and 90 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
.DS_Store .DS_Store
node_modules node_modules
/.direnv/
/build /build
/.svelte-kit /.svelte-kit
/package /package

View File

@@ -11,7 +11,8 @@
Mesh, Mesh,
Points, Points,
Triangle, Triangle,
DoubleSide DoubleSide,
Sphere
} from 'three'; } from 'three';
import { degToRad } from 'three/src/math/MathUtils.js'; import { degToRad } from 'three/src/math/MathUtils.js';
import { MeshBVH } from 'three-mesh-bvh'; import { MeshBVH } from 'three-mesh-bvh';
@@ -49,116 +50,79 @@
// need to build bvh live while generating the slices, so angle checks can be done with // need to build bvh live while generating the slices, so angle checks can be done with
// respect to the closest point in the slice // respect to the closest point in the slice
const bvh = new MeshBVH($stl); const bvh = new MeshBVH($stl);
let indices: [number, number, number][] = []; const positions = bvh.geometry.getAttribute('position');
const positions = $stl.getAttribute('position'); const index = bvh.geometry.index!;
console.log($stl.index);
const qualifyingTriangles = Array.from({ length: index.count / 3 }, () => false);
let qualifyingTrianglesCount = 0;
const triangle = new Triangle(); const triangle = new Triangle();
const normal = new Vector3(); const normal = new Vector3();
for (let i = 0; i < $stl.index!.count; i += 3) { for (let i = 0; i < index.count / 3; i++) {
triangle.setFromAttributeAndIndices( triangle.setFromAttributeAndIndices(
positions, positions,
$stl.index!.array[i], index.array[i * 3],
$stl.index!.array[i + 1], index.array[i * 3 + 1],
$stl.index!.array[i + 2] index.array[i * 3 + 2]
); );
triangle.getNormal(normal); triangle.getNormal(normal);
const angle = normal.angleTo(bedNormal); const angle = normal.angleTo(bedNormal);
if ((angle > Math.PI / 2 ? Math.PI - angle : angle) < maxNonPlanarAngle) { if ((angle > Math.PI / 2 ? Math.PI - angle : angle) < maxNonPlanarAngle) {
indices.push([$stl.index!.array[i], $stl.index!.array[i + 1], $stl.index!.array[i + 2]]); qualifyingTriangles[i] = true;
qualifyingTrianglesCount++;
} }
} }
const pointIndex = Array.from({ length: 3 }, (_, j) => const spheres = Array.from({ length: 3 }, () => new Sphere());
Array.from({ length: positions.count }, (_, i) => i).sort( const vectors = Array.from({ length: 3 }, () => new Vector3());
(a, b) => positions.array[a * 3 + j] - positions.array[b * 3 + j] const surfaces: number[][] = [];
) while (qualifyingTrianglesCount > 0) {
); const faceIndex = qualifyingTriangles.findIndex((it) => it);
function findNearby(i: number): number[] { qualifyingTriangles[faceIndex] = false;
const a = [positions.array[i * 3], positions.array[i * 3 + 1], positions.array[i * 3 + 2]]; qualifyingTrianglesCount--;
const ia = [-1, -1, -1]; console.log(qualifyingTrianglesCount);
// binary search for the closest points in x, y and z const surface = [faceIndex];
for (let j = 0; j < 3; j++) { let cursor = 0;
let d = Math.floor(pointIndex[j].length / 2); while (cursor < surface.length) {
for (let i = 0; i < 3; i++) {
vectors[i].fromBufferAttribute(positions, index.array[surface[cursor] * 3 + i]);
spheres[i].set(vectors[i], tolerance);
}
inner: while (d / 2 >= 1) { bvh.shapecast({
const value = positions.array[pointIndex[j][d] * 3 + j]; intersectsBounds(box, _isLeaf, _score, _depth, _nodeIndex) {
const diff = value - a[j]; return spheres.some((sphere) => box.intersectsSphere(sphere));
if (Math.abs(diff) < tolerance) { },
ia[j] = d; intersectsTriangle(triangle, triangleIndex, _contained, _depth) {
break inner; if (
} else if (value < a[j]) { qualifyingTriangles[triangleIndex] &&
d = Math.floor(d / 2); spheres.some((sphere) => triangle.intersectsSphere(sphere))
} else { ) {
d = Math.floor(d + d / 2); qualifyingTriangles[triangleIndex] = false;
qualifyingTrianglesCount--;
console.log(qualifyingTrianglesCount);
surface.push(triangleIndex);
}
} }
} });
if (ia[j] === -1) return [];
}
while ()
}
bvh.shapecast({
intersectsBounds(box, isLeaf, score, depth, nodeIndex) {
// TODO
},
intersectsTriangle(triangle, triangleIndex, contained, depth) {
// TODO
}
})
const connectedPoints: number[] = Array.from({ length: positions.count });
let connection = 0;
for (let i = 0; i < connectedPoints.length; i++) {
if (connectedPoints[i] !== undefined) continue;
connectedPoints[i] = i;
let connected;
while ((connected = connectedPoints[pointIndex[0][connection]]) !== undefined) {
connectedPoints[pointIndex[0][connection]] = i;
connection++;
}
connection++; cursor++;
} }
surfaces.push(
const faceConnections = new Map<number, number[]>(); surface.flatMap((face) => [
function spatialHash(i: number) { index.array[face * 3],
return ( index.array[face * 3 + 1],
(positions.getX(i) * 19349663) ^ index.array[face * 3 + 2]
(positions.getY(i) * 83492791) ^ ])
(positions.getZ(i) * 73856093)
); );
} }
for (let faceIndex = 0; faceIndex < indices.length; faceIndex++) {
let surface: number[] | undefined = undefined; console.log(surfaces);
const values = indices[faceIndex].map((i) => {
const hash = spatialHash(i);
const value = faceConnections.get(hash);
surface ??= value;
return [hash, value] as const;
});
surface ??= [];
surface.push(faceIndex);
for (const [hash, original] of values) {
faceConnections.set(hash, surface);
if (original && original !== surface) {
surface.concat(original);
}
}
}
const surfaceSet = new Set(faceConnections.values());
const iterator = surfaceSet.values();
const surfaces = Array.from({ length: surfaceSet.size }, () => {
const value = iterator.next().value;
return Array.from(
{ length: value.length * 3 },
(_, i) => indices[value[Math.floor(i / 3)]][i % 3]
);
});
surface = new BufferGeometry(); surface = new BufferGeometry();
surface.setAttribute('position', positions); surface.setAttribute('position', positions);
surface.setAttribute('normal', $stl.getAttribute('normal')); surface.setAttribute('normal', $stl.getAttribute('normal'));
surface.setIndex(surfaces[1].flat()); surface.setIndex(surfaces[0].flat());
/*const hull: [position: Vector3, index: number][][] = []; /*const hull: [position: Vector3, index: number][][] = [];
let limit = 0; let limit = 0;