Dynamic CSG2 cutting and creation of sub meshes

I need to be able to load an stl dynamically, which could be any shape or size, and apply a “cookie cutter” mesh to the loaded stl source, slicing it into 8 smaller meshes that can each be individually rotated and manipulated. Before the slicing occurs, the user can drag the cookie cutter around to find the best location on their loaded file to slice at. I have a few questions:

  1. In this first playground link below, click the “Apply CSG cut” button to break the object into smaller pieces. How do get 8 sub meshes from a cut like this that I can individually rotate and assign positions to?

    https://playground.babylonjs.com/#RDBTFN#2

  2. I’m using masks and shaders to try and reduce how much of the cutter is actually shown, and allowing a user to move the cutter object by clicking shift while dragging. As you can see by comparing the previous link to this next one, the shaders and masks have resulted in a near skin tight red representation for the location of the cutter on the surface. Perfect. But, once you rotate the object around, you’ll see that the hidden geometries of the cutter are still obscuring loaded mesh when rotating around. How can I get that surface level detail showing exactly where the CSG cutting will occur without having it hiding the rest of that object? ( remember that this will change based on the geometries of the loaded stl file ) I don’t mind going in a totally different direction here if masking and shaders are not the way to go. As long as the user can drag that red representation of the cutter around live ( hit shift key and drag ) I don’t care how this is resolved. Any thoughts?

    THANK YOU IN ADVANCE FOR ANY HELP YOU CAN GIVE HERE!

    https://playground.babylonjs.com/#RDBTFN#3

1 Like
  1. csg will only create one final mesh so I would advise to do 8 times the same kind of operations to get each part separately.
  2. I am not sure to understand the question, can you share screenshots of the issue ?

Maybe one way to do this is:

  • take the main mesh, grow by small amount
  • subtract main mesh, retain “surface” csg2
  • intersect all slicer meshes with surface
  • this hopefully highlights slicer entry points into main mesh

It will take some effort to make this fast enough for UI, but CSG2 is fast enough to enable it if you save the correct intermediate CSG2 objects.

See my CSG2 sphere posts that show how quick CSG2 can be.

Edit: here

And here

@sebavan @HiGreg thanks for your replies guys. More info:

Take a look at images 1-4 below.

In my example, I”m cutting this green sphere into 8 pieces with a pattern/template mesh. The green sphere represents any stl file mesh that a user can upload, but the cutting pattern will always be the same. ( image 1 and image 2 ). user needs to be able to drag around that cutting template and place anywhere on their loaded mesh, hit a button, and now they have 8 unique objects. ( image 2 ) instead of doing this 8 times with 8 copies, is there a faster way ? large geometries loaded could take 20 mins for 8 cuts. can I somehow access the resulting sub meshes so I can rotate them and move them independent of each other?

second question: instead of having the user drag this giant pattern around the screen ( image 1 screen shot) which is cumbersome and hard to see around, I’d like to have something that represents the location of the cutter template that is tight on the intersections. (image 4) a user can drag around this representation live, instead of performing a live CSG on an uploaded stl mesh as the user drags, which could be very costly with large geometries, I’m hoping to use masks and shaders for the user to drag this fake cutter into a final position. once the user hits “cut” button, I will apply the location of the fake cutter to the real one, and slice the object into its 8 pieces.

Looking at my link: https://playground.babylonjs.com/#RDBTFN#3

I’m currently very close to figuring this out, if you see my playground… but the masking shaders really only allow you to see one portion of the cut at a time. ( image 3)

How do I go from my current code (image 3 and link ) to what I really want, which is image 4? I don’t really care if its shaders or making or whatever, as long as its less obstructed, and still can be drug around any mesh to help find its final position for cutting.

Thanks again guys. I’ve been cranking 60 hour weeks on the actual complete app for months, and I’m 99% of the way there. Really appreciate you helping me get over the finish line.

image 1

Were you able to try my steps of creating a singular cutter shape from 8 individual. Then create a surface shape from the cutee. Then use a single csg2 intersection per user movement to recreate a surface mesh for displaying result as the user moves around.

Be sure to retain the intermediate CSG2 objects and not recreating them from meshes each time.

I would think a quick feasibility/demonstration is first, then look for optimizations.

If needed, a mesh simplification of the “surface mesh” might speed up the user interface.

As an alternative, a mesh decal might work here, too.

OK GUYS! GOT THE HARD PART! Using a variation of Greg’s example, I am able to drag that surface intersection, and it just looks amazing. Very fast and clean. Only remaining item is the question related to manipulating the 8 pieces that were cut. Any guess as to how to rotate and move position of each mesh? can I break apart the code somehow and say like const newMesh1 = cutMesh[0].someMesh thing…. newMesh1.x = XXXX. etc?

Interesting. Are you saying that executing the “full cut” looks good and is a single mesh object? I wonder in the conversion from CSG2 back to a mesh if the now-disjoint surfaces are implemented as Babylon submeshes.

Print the final mesh object to console and have a look at it to see.

@HiGreg - my thanks for your patience. My math brain works well, but my “wordin’ brain” could use some improvement :slight_smile: .

Your approach to build a system where I can drag the cutter around live using CSG2 is working exactly as I wanted. I am able to cut my object exactly as I wanted to as well, with the cookie cutter being in the correct position, and creating a mesh that appears like it has been cut into 8 smaller meshes.

The last stage is to somehow manipulate each of those 8 pieces so that I can rotate them and reposition them. I’m hoping to find some function that can take my mesh, and break it into 8 new meshes that I can independently control.

I ran a console log on the mesh after the cut, and I get what seems to be an infinite loop of nested child meshes under submeshes, but the submesh array only shows 1 mesh each time:

subMeshes: [e] (Array(1) when opened)
0: e
_mesh: t
subMeshes: [e] (Array(1) when opened)
0: e
_mesh: t

I drilled down about 20 levels deep and gave up.

Any ideas? Thanks again

Are there any child meshes?

Digging through manifold source code, there are some concepts of multiple meshes in a scene. But babylon source code includes calling merge() on the manifold mesh object.

I’m not sure how to get multiple meshes from manifold, and doubly unsure how babylon handles that.

Here’s a playground that separates the meshes with gizmos attached, It’s unoptimized but gets the job done fast and shows you how, you don’t really need external tools to do this. It’s pretty straight forward. It can be cleaned up and sped up to be even more efficient. Check your messages :wink:
I’ve already asked if this was done, but you look busy trying to solve it. Like I said, it’s unoptimized but gives you the basis for splitting parts AND gizmos.

1 Like

Exactly the approach I was going to suggest, but didn’t have time to write. This is awesome!

If I’m reading your code correctly:

  • go through vertices and those close to each other: make them the same index (collapseVertices)
  • go through all triangles (every 3 indices) ,
  • group indices by adding all triangle indices that share any index with existing triangle
  • each set is a different mesh

collapseVertices looks similar to mesh.optimizeIndices(), but optimizeIndices doesn’t remove vertices. Hmmm…looks like collapseVertices also doesn’t remove vertices.

Note that collapsingVertices() checks for each pair of x,y, and z values rounding to the same (closest) integer multiple of epsilon. Not sure if there’s a better way, but this may be totally sufficient.

You could create submeshes with some extra work, which might optimize space, but with each a separate mesh, it may be more useful for any subsequent use.

Overall, great implementation!

1 Like

Oh, there’s many better ways. This was just fast and for clarity on how to find a solution without clouding the details.

When checking spatially, yes,use epsilon values. In this case, as you described in order to account for floating point errors and inaccuracies.

Hey HiGreg and @ntech - thanks for all of the feedback. I wanted to verify - that playground you sent is not for the individual manipulation of the submeshes, but rather the control of that cutter, right? I know this is a long thread :slight_smile: I stated earlier that I had that part figured out and working, so no need to focus on that any more. At this point, I’m looking for a way to manipulate those 8 pieces that are sliced individually as independent meshes. If this is what your playground does, first of all, thank you, but second - I don’t actually see it working? Any advice on how I can rotate just the top left cut piece for example?
Thanks again, and GREAT COMMUNITY!!! Everyone here is just amazing. Thanks for all the feedback

Well here’s the one issue.. It does have a phantom object. I’ll go back over it and send a new one.. Just move the phantom out of the way and you can select the individual slices, the 8 of them. They are individual meshes at that point can can be manipulated on their own in that playground.

Clarification: maskRoot is pickable and that’s the “phantom” I’m referring to here.

Update: Here’s the new playground that disables picking for all non part objects so you can see it works.. I’m getting shader errors on your original playground, and no, I didn’t fix those.. but this will get maskRoot and the cutter out of the way so you can test the object parts.

To answer your original question, it was using your cutter playground. I added the mesh splitting and picking w/ gizmos. Only difference is they are now full meshes instead of submeshes but that can be done either way. They are all fully pickable and you can manipulate each individual part as you reqeusted.

Yep. This is 100% it. Fantastic. Thank you and @HiGreg for all of your help and advice. You guys nailed it. I’ll post my url for the app once it launches, and share any of my code that’s applicable here.

Thanks again. Really appreciate all the assistance.

2 Likes

YW. I already wrote the submesh supported function if you need it.