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;
}