Jump to content

Voronoi - dynamic - location based fracture (WIP)


johner

Recommended Posts

btw, are you storing the inside faces onto a group when they are being created?

Yeah, there's an outside and inside group like from the Shatter SOP.

Ugh, I just realized I've been calling these flipbooks "playblasts" (shudder - Maya hangover)

Link to comment
Share on other sites

OK, so documentation and examples next, but I wanted to describe one feature I implemented trivially this morning in one of those incredibly cool "power of Houdini" moments.

Some background:

The Voronoi fracture SOP takes two inputs: the mesh to fracture, and the points around which to build each Voronoi cell. So, assuming that all of the points come from within the volume of the mesh, you'll get one piece/fragment per point. This is really nice, since it gives you complete control over the number and placement of the fragments. Anywhere there is a higher density of points, you'll get more, smaller fragments. So to get location-based fracturing to work, you just have to generate more points closer to the impact location.

Within the SOP Solver of the Fracture Solver asset the basic algorithm for fracturing looks like this:

--Test object is big enough, impact hard enough for fracture

--If so, snap impacts to surface of object with Ray SOP set to MinDistance

--Copy a metaball of user-defined radius to each impact point, call this the "impact zone"

--Create a signed distance function from the metaballs with IsoOffset in Metaballs mode

--Normalize and invert this by dividing by the minimum value of the SDF and clamping to (0,1)

--At this point you have a density volume that ranges from 1 at the impact point, falling off to 0 at the outside of the impact radius

--Merge in the current object's collision SDF and intersect the impact volume with that

--Scatter points by density in the resulting volume and feed to the Fracture SOP

So you get more points the closer to "ground zero" you are to the impact, which leads to more, smaller, fragments.

The "Visualize Impact Region" feature works by just feeding the un-intersected impact volume to a VOP Sop that does a VolumeSample and maps the impact density at a given point to a red/white ramp.

Anyway, I'd been thinking about how to do explosion-based fracturing, i.e. non-impact based fracturing based on how much within the blast radius of an explosion a particular object is. A good way to do explosions is by attaching animated, quickly expanding metaball geometry to a Magnet Force DOP with a large negative force scale. That metaball geometry defines the blast radius. You might see where this is going.

I realized all I had to do was ObjectMerge the metaball geometry from any Magnet Forces attached to a given object, and merge those with the metaballs from any impacts to create the overall "impact zone" described above. Then all the various SDF manipulations are exactly the same. So, an ObjectMerge, a Merge, and a couple of Switch SOPs to enable/disable the feature, and I had Magnet Force explosion fracturing. It was literally four SOPs. How cool is that? Flipbook:

here

Link to comment
Share on other sites

i've been trying to stay off this thread because i can't stand the tingling feeling of being teased... but i have to say that this is some of the most impressive demonstration of what this software is all about - it's looking great, and i can't wait to see where you're gonna take it next. ingenious.

cheers,

Abdelkareem

Link to comment
Share on other sites

Someone's having way too much fun around here. :)

Heh, yeah I think I went a little fanboy there when I realized how easy it was to implement explosions. Chasing down all the external references in my assets and replacing them with 100-character stamp expressions has temporarily cured me of that.

i've been trying to stay off this thread because i can't stand the tingling feeling of being teased... but i have to say that this is some of the most impressive demonstration of what this software is all about - it's looking great, and i can't wait to see where you're gonna take it next. ingenious.

cheers,

Abdelkareem

Thanks a lot, Abdelkareem, I appreciate it. No teasing; I really am close to getting something out there. Depends on how much time I get to work on it over the weekend (Memorial Day weekend here in the States - lots of family stuff)

Have you done any kind of stress test of this that you can post? I'm curious to see how this could handle, say, over 2,000 pieces at one time.

Well, it depends on whether you're talking about pre-fractured or dynamically fractured. The last test on the first post in this thread was about 1000 pieces. I don't know how long that took to fracture - I let it fracture and sim overnight, but I'm guessing a while. The limiting factor at the moment is mainly mesh complexity.

There's a lot of speedups I'll need to do after the first release - it's pretty brute force at the moment. To fracture a relatively simple object like in these examples into 30-40 pieces is quite fast. There's a delay of a few seconds when it's fracturing and DOP is building the SDF for the new pieces during the sim, but it's not bad. That example I posted along with the screenshot I think was about 350 pieces and was quite reasonable to sim.

On the other hand, fracturing a 15,000 poly version of the Armadillo into 460 pieces took something like 25 minutes. Again, mesh complexity is the killer. One nice thing, as I'm working on speeding it up, the Fracture SOP builds each piece individually, and you can give it a point group expression for which input points you want to build pieces from. So you can actually put an expression in there that builds, say 50 of the pieces per frame, point a Geometry ROP output at that, and distribute the fracture process across processors / machines. Then just stick a File SOP within a ForEach SOP and merge the pieces back together. I'll put an example of doing that in the release.

Edited by johner
Link to comment
Share on other sites

Have you done any kind of stress test of this that you can post? I'm curious to see how this could handle, say, over 2,000 pieces at one time.

Just another data point on this, I did a big glass-shattering type test in the background while I worked on docs and such. Flipbook is:

here.

It went from one box to about 1300 pieces, and took about an hour to sim. Almost all of that was the RBD Simulation. Each fracture operation was just fracturing a box (or piece of it) into 80-90 pieces, which is a really straightforward, pretty quick operation. Calculating the SDF's and, mainly, doing the actual sim dwarfs any fracturing for a case like this. Couple of reasons for the sim being slow: 1) Because the fracture has to happen after DOPs has handled the collision, the transition from whole to fractured generally looks and behaves better if you substep the entire DOPNet. Here I did four substeps, though you can often get away with two. 2) The fractured pieces in general, but especially in this case, tend to be big, convex, low-poly objects, and to avoid interpenetration you need to switch the Surface collision representation from Points to Edges and toggle on Triangulate, which slows things way down.

One thing I plan on investigating at some point is convex hull support in H10's open source ODE Solver. I know from working with it a few years back that ODE supports convex hulls as a collision rep, but H10 doesn't seem to expose that (is that right?). Every object in this particular sim is a convex hull, so you'd think ODE might speed it up a fair bit, and that should generally be the case for debris-type sims from this fracture operation.

Link to comment
Share on other sites

One thing I plan on investigating at some point is convex hull support in H10's open source ODE Solver. I know from working with it a few years back that ODE supports convex hulls as a collision rep, but H10 doesn't seem to expose that (is that right?). Every object in this particular sim is a convex hull, so you'd think ODE might speed it up a fair bit, and that should generally be the case for debris-type sims from this fracture operation.

If I'm reading this correctly, are you saying that if "convex hull" is supported in Houdini's ODE implementation, we can get your automatic, location-based fracture with the speed of ODE? :blink:

Edited by melazoma
Link to comment
Share on other sites

If I'm reading this correctly, are you saying that if "convex hull" is supported in Houdini's ODE implementation, we can get your automatic, location-based fracture with the speed of ODE? :blink:

Well, theoretically. I haven't spent enough time with the ODE implementation to know for sure. But all the fracturing really needs to know is a list of impacts and their magnitude (and ideally, object volume, but you could use mass), and have the ability to create objects dynamically, control their initial velocity, and have the solver calculate the required physical properties for the new pieces. The DOPs RBD Solver is pretty bulletproof as far as that stuff goes, but I don't know about the ODE implementation. And, of course, H10's ODE solver would need to support the convex hull collision representation. Physics engines that are geared towards real-time like ODE, Bullet, PhysX, Havok, all tend to support convex hulls as a collision primitive because you can do fast intersection tests between them. The pieces generated by a Voronoi fracture of a convex object are guaranteed to be convex hulls (the situation in the "glass" sim above). And even for concave objects, by the time you fracture them they are pretty convex and I think you could get away with using a convex hull representation in a lot of cases.

Here's a test I did last night of dynamic fracturing of a concave object. Even though Houdini's DOPs solver will generate a collision SDF that represents the accurate boundary of the screwdriver, for a sim like this you really don't need that kind of accuracy. And the resulting fragments are pretty close to convex and would probably do fine represented as such.

This is a case, by the way, where the DOPs solver did great and the biggest delays were the fracturing. Fracturing the 2200 triangle screwdriver into 60 pieces took about 20 seconds each time, but I only did two substeps and kept the Surface collision rep as Points and the sim was nice and quick and looks fine, I think.

Edited by johner
Link to comment
Share on other sites

OK, sorry for the delay, here's the first release. There's two example files in here, one for basic fracturing and one for dynamic fracturing. I'd recommend starting with the basic fracturing and start at the top and work your way down through the subnets there, then do the same for the dynamic fracturing. There's also a README file that has some documentation and tips on various techniques for fracturing and dynamics. Most of tests I've shown in this thread are in the dynamic fracturing example file in one form or another.

I also put a rough, stream-of-consciousness TODO.txt file in there. I'd be particularly interested in feedback on priorities on where to go from here, as well as questions, bugs and such of course.

I've only tested this on Linux, but any code in here is just Vex and standard HOM Python, so it should work everywhere. Let me know if it doesn't.

voronoi_fracture.tar.gz

  • Like 1
Link to comment
Share on other sites

This all looks very interesting, and very well put together, not to mention very cool.

Just poking around quickly is there a reason not to use the divide sop to cap your cuts rather than a python node, from recent experience I say python nodes aren't anywhere near as fast as native ones.

Also, here's a little idea, I've taken your basic pre-fractured sphere and lumped in some noise so that the pieces don't have straight edges, it's an old trick but a goody...

basic_fracture_example_with_noise.hipnc

Edited by sibarrick
Link to comment
Share on other sites

OK, sorry for the delay, here's the first release. There's two example files in here, one for basic fracturing and one for dynamic fracturing. I'd recommend starting with the basic fracturing and start at the top and work your way down through the subnets there, then do the same for the dynamic fracturing. There's also a README file that has some documentation and tips on various techniques for fracturing and dynamics. Most of tests I've shown in this thread are in the dynamic fracturing example file in one form or another.

I also put a rough, stream-of-consciousness TODO.txt file in there. I'd be particularly interested in feedback on priorities on where to go from here, as well as questions, bugs and such of course.

I've only tested this on Linux, but any code in here is just Vex and standard HOM Python, so it should work everywhere. Let me know if it doesn't.

Awesome, checking this out right now, also running on WinXP 64bit, all runs well.

Link to comment
Share on other sites

This all looks very interesting, and very well put together, not to mention very cool.

Just poking around quickly is there a reason not to use the divide sop to cap your cuts rather than a python node, from recent experience I say python nodes aren't anywhere near as fast as native ones.

Thanks, Simon. I thought I'd tried every conceivable way to cap the cuts using built-in tools, but I'm embarassed to admit I don't see how to do it with Divide SOP. Can you help me out there? For a while I used Triangulate2D followed by Divide with "Remove Shared Edges" on. This works well as long as you have convex input, in which case all your cuts will be convex polygons. I couldn't figure out a generic way to cap with concave polygons. I tried PolyCap, but the points as created from the Clip SOP are out-of-order, i.e. new points come last, and they can share the polygon with old points, so you end up having to sort by neighbour information anyway. For a while I used an Add SOP with a version of the code that ended up in the Python SOP as an expression, but we all know Houdini evaluates expressions more often than you want sometimes.

And the Add SOP didn't easily deal with multiple holes created by cutting a concave object. I needed to group the points on the edge with something like Connectivity/Partition, but restricted to just the points on the clip edge. And I'd need another ForEach loop to cap each hole, as I don't think any of the built-in SOPs will handle that case (??).

So for a while I had a "Input is Convex" toggle on the asset that used Triangulate2D if on and the Python SOP when off, but I saw little performance difference so I took it out. That was before I tested many hi-res meshes, however, where the Python SOP really seems to bog down when creating the new polygon, so I might have to revisit.

Please let me know if I'm missing something. Believe me, I'd love to get rid of the Python SOP and use something built-in. One of my TODO's is to speed the capping way up, since Fracture obviously does a ton of it in the inner loop.

Also, here's a little idea, I've taken your basic pre-fractured sphere and lumped in some noise so that the pieces don't have straight edges, it's an old trick but a goody...

Ha, that is a good one! Took me a second to figure out what was going on there, so I don't think I would ever have thought of that, thanks! The geometry coming out isn't quite as clean, but it sure is more interesting looking, and a Divide SOP on the "inside" group goes a long way. I'll have to figure out a good way to add that as an option. Thanks again.

Link to comment
Share on other sites

Thanks, Simon. I thought I'd tried every conceivable way to cap the cuts using built-in tools, but I'm embarassed to admit I don't see how to do it with Divide SOP. Can you help me out there?

Well maybe I'm missing something myself, it sounds like you nearly did it this way, we do literally thousands of capping operations on cut geometry, cut with a clip sop, and then just use the divide sop with "remove shared edges" turned on afterwards, that's it. That will give you a poly that is concave or convex, generally I have to then follow that up with a bricker because I need internal points but it doesn't look like you need that. You might also need to fuse all points before the divide sop, and I tend to use a second clip on the result with a tiny offset just in case the input geometry isn;t properly closed, but again your stuff seems pretty water tight, and would fail with your python sop method if that was an issue so I guess you shouldn't need that.

So in summary

input geometry

fuse sop

clip sop

divide sop - remove shared edges

reverse sop (i think the divide sop used this way always flips the primitive normals for some reason, but that might just be because I have Houdini 4.0 compatibilty on, so try it)

you can also sling in a hole sop if you expect nested edge loops as a result of the clip, e.g slicing horizontally through a torus.

finally merge the divide sop result with the clipped version, and fuse to taste.

Edited by sibarrick
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...