Hi there! I’m working with your CGAL wrapper (fantastic resource- thanks!), and I’m having some issues with the boolean operations. I think I might just be defining the issue wrong, but was hoping to ask your advice?
I’m trying to find the unique volumes of a set of gameobjects. In order to do this I take the union of all of them, then one by one I intersect the other gameobjects with each other, then finish by taking the difference between the union and the intersected components.
However, for some reason I need to translate the intersections by a small amount to make the DIFFERENCE code work? I wonder if I’m doing something wrong, or there’s an issue with the underlying algorithm?
Any help would be really appreciated!
public void PerformVolumetricBooleanOperations(GameObject[] inputGos) { // in this function we find the union of all the gameobject volumes. // we then find the volume that is unique to those volumes. var boolean = MeshProcessingBoolean<EEK>.Instance; // we also need to convert all the gameobjects to cgal polyhedra. var polyhedra = new Polyhedron3<EEK>[inputGos.Length]; for (int i = 0; i < inputGos.Length; i++) { polyhedra[i] = ConvertGoToPolyhedron(inputGos[i]); } // now, let's produce a union of all the polyhedra. var unionPoly = new Polyhedron3<EEK>(); for (int i = 0; i < polyhedra.Length; i++) { if (!boolean.Op(POLYHEDRA_BOOLEAN.UNION, unionPoly, polyhedra[i], out unionPoly)) { Debug.Log("BooleanOperation has failed");// this is probably because one mesh completely encompasses/equals another. } } // now we can produce the bits which are unique to each gameobject. // to do this, we take the union of all the overlaps between every pairwise combination of gameobjects. // once we have this, we can take the difference between this and the union object we calculated above. var intersectionsUnion = new Polyhedron3<EEK>(); for (int i = 0; i < polyhedra.Length; i++) { var tempPoly = new Polyhedron3<EEK>(); for (int ii = i + 1; ii < polyhedra.Length; ii++) { if (boolean.Op(POLYHEDRA_BOOLEAN.INTERSECT, polyhedra[i], polyhedra[ii], out tempPoly)) { boolean.Op(POLYHEDRA_BOOLEAN.UNION, intersectionsUnion, tempPoly, out intersectionsUnion); } } } // there is a bit of an issue with taking the difference between union and intersections. i think it might be because there's too perfect an overlap?. this seems to solve it, but i don't like it. intersectionsUnion.Translate(new Vector3d(0.0000001)); // as a check, you can uncomment the below, and you should see gameobjects appear that are the union, and the union of intersections //unionPoly.ToUnityMesh("union of all gameobjects", new Material(Shader.Find("Diffuse")), false); //intersectionsUnion.ToUnityMesh("union of all intersections", new Material(Shader.Find("Diffuse")), false); var intersectionsUnionInversion = new Polyhedron3<EEK>(); boolean.Op(POLYHEDRA_BOOLEAN.DIFFERENCE, unionPoly, intersectionsUnion, out intersectionsUnionInversion); intersectionsUnionInversion.ToUnityMesh("All unique volumes", new Material(Shader.Find("Diffuse")), false); } Polyhedron3<EEK> ConvertGoToPolyhedron(GameObject go) { // this takes a unity gameobject, and turns it into an EEK polyhedron (middle accuracy, middle speed). // to convert back, just call .toUnityMesh() on the polyhedron itself. Vector3[] unityMeshPoints = go.GetComponent<MeshFilter>().mesh.vertices; Point3d[] cgalMeshPoints = new Point3d[unityMeshPoints.Length]; for (int i = 0; i < unityMeshPoints.Length; i++) { cgalMeshPoints[i] = unityMeshPoints[i].ToCGALPoint3d(); } var polyhedron = new Polyhedron3<EEK>(cgalMeshPoints, go.GetComponent<MeshFilter>().mesh.triangles); polyhedron.Translate(new Point3d(go.transform.position.x, go.transform.position.y, go.transform.position.z)); return polyhedron; }