ToDo: slice cap meshes by slicing planes

This commit is contained in:
Fuhrmann 2025-03-05 15:11:51 +01:00
parent c33a39944a
commit 07208177fd

View file

@ -405,14 +405,14 @@ function generateCapMeshes(meshes: Mesh[], plane: Plane) {
const capMesh = new Mesh(geometry, material); const capMesh = new Mesh(geometry, material);
// Offset mesh to avoid flickering // Offset mesh to avoid flickering
const offset = 10; const offset = -1;
const normal = plane.normal.clone().multiplyScalar(offset); const normal = plane.normal.clone().multiplyScalar(offset);
const positionAttr = capMesh.geometry.attributes.position; const positionAttr = capMesh.geometry.attributes.position;
for (let i = 0; i < positionAttr.count; i++) { for (let i = 0; i < positionAttr.count; i++) {
const x = positionAttr.getX(i) - normal.x; const x = positionAttr.getX(i) + normal.x;
const y = positionAttr.getY(i) - normal.y; const y = positionAttr.getY(i) + normal.y;
const z = positionAttr.getZ(i) - normal.z; const z = positionAttr.getZ(i) + normal.z;
positionAttr.setXYZ(i, x, y, z); positionAttr.setXYZ(i, x, y, z);
} }
positionAttr.needsUpdate = true; positionAttr.needsUpdate = true;
@ -474,49 +474,15 @@ function buildPolygons(edges: Array<[Vector3, Vector3]>): Vector3[][] {
return polygons; return polygons;
} }
// Function to triangulate the sliced polygon vertices
function triangulatePolygon(vertices: Vector3[], plane: Plane) { function triangulatePolygon(vertices: Vector3[], plane: Plane) {
// Project vertices to the plane // Choose a reference point on the plane (centroid of the vertices)
const projectedVertices = projectVerticesToPlane(vertices, plane);
// Sort vertices in counter-clockwise order
const sortedVertices = sortVertices(projectedVertices);
// Convert the sorted 2D vertices back to flat array
const flatVertices: number[] = [];
sortedVertices.forEach((v) => {
flatVertices.push(v.x, v.y);
});
// Use earcut to triangulate the 2D polygon (returns an array of indices)
const indices = earcut(flatVertices);
// Create geometry for the triangulated result
const geometry = new BufferGeometry();
const positions: number[] = [];
vertices.forEach((v) => {
positions.push(v.x, v.y, v.z);
});
geometry.setAttribute(
"position",
new BufferAttribute(new Float32Array(positions), 3)
);
geometry.setIndex(indices);
return geometry;
}
function projectVerticesToPlane(vertices: Vector3[], plane: Plane) {
// Choose a reference point on the plane (e.g., centroid)
const planeOrigin = vertices const planeOrigin = vertices
.reduce((sum, v) => sum.add(v), new Vector3()) .reduce((sum, v) => sum.add(v.clone()), new Vector3())
.divideScalar(vertices.length); .divideScalar(vertices.length);
// Define local 2D coordinate system on the plane // Construct the local 2D coordinate system
const N = plane.normal.clone().normalize(); const N = plane.normal.clone().normalize(); // Plane normal
let T = new Vector3(1, 0, 0); let T = new Vector3(1, 0, 0); // Temporary vector for tangent
// Ensure T is not parallel to N // Ensure T is not parallel to N
if (Math.abs(N.dot(T)) > 0.9) { if (Math.abs(N.dot(T)) > 0.9) {
@ -526,29 +492,37 @@ function projectVerticesToPlane(vertices: Vector3[], plane: Plane) {
const U = new Vector3().crossVectors(N, T).normalize(); // First tangent const U = new Vector3().crossVectors(N, T).normalize(); // First tangent
const V = new Vector3().crossVectors(N, U).normalize(); // Second tangent const V = new Vector3().crossVectors(N, U).normalize(); // Second tangent
// Project each vertex to 2D space in the plane const projectedVertices = vertices.map(
return vertices.map((v) => { (v) =>
const relativePos = v.clone().sub(planeOrigin); new Vector2(
return new Vector2(relativePos.dot(U), relativePos.dot(V)); v.clone().sub(planeOrigin).dot(U),
}); v.clone().sub(planeOrigin).dot(V)
)
);
// Prepare flat array for triangulation
const flatVertices: number[] = projectedVertices.flatMap((v) => [v.x, v.y]);
// Perform triangulation
const indices = earcut(flatVertices);
// Create geometry
const positions: number[] = vertices.flatMap((v) => [v.x, v.y, v.z]);
const geometry = new BufferGeometry();
geometry.setAttribute(
"position",
new BufferAttribute(new Float32Array(positions), 3)
);
geometry.setIndex(indices);
return geometry;
} }
function sortVertices(vertices: Vector2[]) { // Compute the centroid of a list of 2D vertices
const centroid = new Vector2(0, 0); function computeCentroid(vertices: Vector2[]): Vector2 {
const centroid = new Vector2();
// Compute the centroid of the vertices
vertices.forEach((v) => centroid.add(v)); vertices.forEach((v) => centroid.add(v));
centroid.divideScalar(vertices.length); return centroid.divideScalar(vertices.length);
// Sort vertices by the angle with the centroid
vertices.sort((a, b) => {
return (
Math.atan2(a.y - centroid.y, a.x - centroid.x) -
Math.atan2(b.y - centroid.y, b.x - centroid.x)
);
});
return vertices;
} }
// Function to find the intersection point between an edge and a plane // Function to find the intersection point between an edge and a plane