Issue
I am using three-csg (import CSG from '../../csg/three-csg'
) to perform Boolean unions on multiple meshes (created by extrude geometries). However, when I generate edges using THREE.EdgesGeometry
, the final mesh still contains edges from the original meshes instead of showing only the correct outer edges of the unioned mesh.
Example Workflow:
1. Mesh1, Mesh2, Mesh3 → Three separate meshes
2. Union Step 1
const goodMesh1 = CSG.union(mesh1, mesh2);
Union Step 2:
const finalMesh = CSG.union(goodMesh1, mesh3);
4. Generating Edges:
const edges = new THREE.EdgesGeometry(finalMesh.geometry);
const lineMaterial = new THREE.LineBasicMaterial({ color: 0x000000 });
const edgeLines = new THREE.LineSegments(edges, lineMaterial);
scene.add(edgeLines);
Problem: The generated edges include those of mesh1
and mesh2
, instead of showing only the correct outer edges of finalMesh
.
Thing we tried
Custom OutlinePass (library)
Increased threshold values for angle detection in EdgesGeometry.
Converted geometry to non-indexed (geometry.toNonIndexed()
).
4.Tested with async function to wait for complete union operations
Use mergeVertices
used finalMesh.geometry.computeVertexNormals();
Question:
How can I ensure that EdgesGeometry
only generates the correct external edges after a CSG.union()
operation using three-csg
? Is there a way to remove internal faces before generating edges?
Any insights would be appreciated! Thanks
When you did mergeVertices, did you remove the uv and normal attributes first?
3 Likes
jaxx_sparrow:
three-csg
Before you get too deep into three-csg , try to use Manifold - the most fast/robust CSG JS library.
Not long ago I explored all JS CSG solutions for my present GemDesign project and found that Manifold is the best.
Here is example how to use it from Three.js: Manifold - three.js Example
2 Likes
Hi Manthrax, tried this solution still no difference.
the line is still visible.
below is the code for reference
handleAngleBlunt(edge, opposingEdge, part) {
const { edgeOutwardNormal, opposingEdgeOutwardNormal, angleBetween } = this.determineAngleBetweenEdgesCoreGeometry(edge, opposingEdge)
const angleValidation = (180 - angleBetween) < 89 || (180 - angleBetween) > 91
let bspCornerNext = null
let opposingNextEdge = null
let opposingNextEdgeCore = null
const cornerVertices= this.createCorner(edge, opposingEdge, edgeOutwardNormal, opposingEdgeOutwardNormal, part.inputOrientationUI[0])
const cornerGeom = new THREE.ExtrudeGeometry(new THREE.Shape(cornerVertices), { bevelEnabled: false, depth: edge.layerOccupation.height })
if(opposingEdge.nextEdge && opposingEdge.nextEdge.originalgeometry) {
const nextCorner = this.createCornerGeometry(opposingEdge,opposingEdge.nextEdge, part)
const cornerMeshNext = this.createMesh(nextCorner)
const opposingNext =this.createTransformedMesh(opposingEdge.nextEdge.originalgeometry,opposingEdge.nextEdge.originalMatrix, opposingEdge.nextEdge.originalgeometry.isCsg)
const opposingNextCore =this.createTransformedMesh(opposingEdge.nextEdge.coreGeometry,opposingEdge.nextEdge.coreMatrix, opposingEdge.nextEdge.coreGeometry.isCsg)
bspCornerNext = CSG.fromMesh(cornerMeshNext)
opposingNextEdge = CSG.fromMesh(opposingNext)
opposingNextEdgeCore = CSG.fromMesh(opposingNextCore)
opposingEdge.nextEdge.originalgeometry.isCsg = true
opposingEdge.nextEdge.coreGeometry.isCsg = true
}
const cornerMesh = this.createMesh(cornerGeom)
const edgeMesh = this.createTransformedMesh(edge.coreGeometry,edge.coreMatrix,edge.coreGeometry.isCsg)
const oppEdgeMesh =this.createTransformedMesh(opposingEdge.originalgeometry,opposingEdge.originalMatrix, opposingEdge.originalgeometry.isCsg)
const extendedEdgeMesh =this.createTransformedMesh(opposingEdge.coreGeometry,opposingEdge.coreMatrix,opposingEdge.coreGeometry.isCsg)
const extendedEdgeMeshWithoutCSG =this.createTransformedMesh(opposingEdge.originalgeometryWithoutCsg, opposingEdge.coreMatrix, true)
const bspCornerMesh = CSG.fromMesh(cornerMesh)
const bspEdgeMesh = CSG.fromMesh(edgeMesh)
const bspOppEdgeMesh = CSG.fromMesh(oppEdgeMesh)
const bspExtendedEdgeMesh = CSG.fromMesh(extendedEdgeMesh)
const bspExtendedEdgeMeshWithoutCSG = CSG.fromMesh(extendedEdgeMeshWithoutCSG)
opposingEdge.originalgeometry.isCsg = true
if ((180 - angleBetween) > 91 ) {
// find intersector with next edge and current edge
const bspIntersector = bspMeshNext.intersect(bspEdgeMesh)
const finalMesh = bspIntersector.union(bspCornerMesh)
let bspUnion = finalMesh.union(bspOppEdgeMesh)
let finalMeshNextEdge = bspUnion
const nextEdge = this.convertToMesh(finalMeshNextEdge)
const currentEdge = this.convertToMesh(finalMeshCurrentEdge)
nextEdge.geometry.deleteAttribute('uv');
nextEdge.geometry.deleteAttribute('normal');
// currentEdge.geometry.deleteAttribute('uv');
//currentEdge.geometry.deleteAttribute('normal');
mergeVertices(nextEdge.geometry);
mergeVertices(currentEdge.geometry);
// Recompute normals for better shading
nextEdge.geometry.computeVertexNormals();
currentEdge.geometry.computeVertexNormals();
// Update opposingEdge's coreGeometry
const opposingGeometry = nextEdge.geometry
opposingEdge.coreGeometry = opposingGeometry
// Update currentEdge's coreGeometry
const edgeGeometry = currentEdge.geometry
edge.coreGeometry = edgeGeometry
}
}
createTransformedMesh(geometry, matrix, isCsg = false) {
const mesh = this.createMesh(geometry)
if(!isCsg) mesh.geometry.applyMatrix4(matrix)
return mesh
}
createMesh(geometry) {
return new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: new THREE.Color('green') }))
}
Thanks yesbird for you time will try this and get back to you .
1 Like
I had the similar issue and increasing subdivision was the cure, then I switched to Manifold to increase performance, details are here:
I am trying to apply wireframe on result of CSG subtract operation, library is THREE-CSGMesh by @manthrax (btw, many thanks for this port).
Doing it this way I am getting strange artifact (please see attached image).
wireframe = new THREE.LineSegments(
new THREE.EdgesGeometry( mesh.geometry, 1 ),
new THREE.LineBasicMaterial( { color: 0x888888, linewidth: 2 } ) );
scene.add(wireframe);
[image]
Examining this mesh in console I found nothing special, so I am completely sta…
mergeVertices returns a new geometry.. it doesn’t merge in place.
And you need to mergeVertices Before you do the CSG.. to make the mesh more watertight/manifold, which is the whole point.
(Not saying its guaranteed to work… but doing it after the fact, and not using the result definitely won’t work. )
I suspect you will have the same issues with manifold or mesh-bvh-csg unless you clean up the input meshes.
1 Like