ToDo: slice cap meshes by slicing planes
This commit is contained in:
parent
c33a39944a
commit
07208177fd
1 changed files with 37 additions and 63 deletions
|
@ -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
|
||||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue