mirror of
https://github.com/Theaninova/Bampy.git
synced 2025-12-11 03:56:17 +00:00
89 lines
2.7 KiB
TypeScript
89 lines
2.7 KiB
TypeScript
import { Vector3, BufferGeometry } from 'three';
|
|
import { type SlicerOptions } from '../slicer';
|
|
import { ExtendedTriangle, MeshBVH } from 'three-mesh-bvh';
|
|
|
|
/**
|
|
* Extracts all continuous surfaces that can be printed at the specified angle.
|
|
*/
|
|
export function extractSurfaces(
|
|
options: SlicerOptions
|
|
): [surfaces: MeshBVH[], surfaceTriangles: boolean[]] {
|
|
const qualifyingTriangles = Array.from({ length: options.index.count / 3 }, () => false);
|
|
let qualifyingTrianglesCount = 0;
|
|
const triangle = new ExtendedTriangle();
|
|
const normal = new Vector3();
|
|
for (let i = 0; i < options.index.count / 3; i++) {
|
|
triangle.setFromAttributeAndIndices(
|
|
options.positions,
|
|
options.index.array[i * 3],
|
|
options.index.array[i * 3 + 1],
|
|
options.index.array[i * 3 + 2]
|
|
);
|
|
triangle.getNormal(normal);
|
|
const angle = normal.angleTo(options.bedNormal);
|
|
// TODO: bottom layers
|
|
if (angle < options.maxNonPlanarAngle) {
|
|
qualifyingTriangles[i] = true;
|
|
qualifyingTrianglesCount++;
|
|
}
|
|
}
|
|
|
|
const surfaceTriangles = [...qualifyingTriangles];
|
|
|
|
const surfaces: number[][] = [];
|
|
while (qualifyingTrianglesCount > 0) {
|
|
const faceIndex = qualifyingTriangles.findIndex((it) => it);
|
|
qualifyingTriangles[faceIndex] = false;
|
|
qualifyingTrianglesCount--;
|
|
const surface = [faceIndex];
|
|
let cursor = 0;
|
|
while (cursor < surface.length) {
|
|
triangle.setFromAttributeAndIndices(
|
|
options.positions,
|
|
options.index.array[surface[cursor] * 3],
|
|
options.index.array[surface[cursor] * 3 + 1],
|
|
options.index.array[surface[cursor] * 3 + 2]
|
|
);
|
|
|
|
options.bvh.shapecast({
|
|
intersectsBounds(box, _isLeaf, _score, _depth, _nodeIndex) {
|
|
return triangle.intersectsBox(box);
|
|
},
|
|
intersectsTriangle(target, triangleIndex, _contained, _depth) {
|
|
if (
|
|
qualifyingTriangles[triangleIndex] &&
|
|
target.distanceToTriangle(triangle) < options.tolerance
|
|
) {
|
|
qualifyingTriangles[triangleIndex] = false;
|
|
qualifyingTrianglesCount--;
|
|
surface.push(triangleIndex);
|
|
}
|
|
}
|
|
});
|
|
|
|
cursor++;
|
|
}
|
|
surfaces.push(surface);
|
|
}
|
|
|
|
return [
|
|
surfaces.map((surface) => {
|
|
const geometry = new BufferGeometry();
|
|
geometry.setAttribute('position', options.positions);
|
|
geometry.setAttribute('normal', options.normals);
|
|
const indices: number[] = Array.from({ length: surface.length * 3 });
|
|
for (let i = 0; i < surface.length; i++) {
|
|
const pos = surface[i] * 3;
|
|
indices[i * 3] = options.index.array[pos];
|
|
indices[i * 3 + 1] = options.index.array[pos + 1];
|
|
indices[i * 3 + 2] = options.index.array[pos + 2];
|
|
}
|
|
geometry.setIndex(indices);
|
|
const bvh = new MeshBVH(geometry);
|
|
geometry.boundsTree = bvh;
|
|
return bvh;
|
|
}),
|
|
surfaceTriangles
|
|
];
|
|
}
|