mirror of
https://github.com/Theaninova/Bampy.git
synced 2025-12-11 03:56:17 +00:00
feat: face separation
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
node_modules
|
||||||
|
/.direnv/
|
||||||
/build
|
/build
|
||||||
/.svelte-kit
|
/.svelte-kit
|
||||||
/package
|
/package
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user