# A setup for secondary RBD fracturing

Hey,
This is my first post here, and I thought a good one to start off with is this setup I have made for taking a RBD sim and do another sim for for a secondary fracture.
This can obviously be done in a number of ways, including doing it all in one sim (using constraint networks, dynamic fracturing and so on), but I wanted a setup that allowed me to apply fracturing on top an existing simulation.

For the setup I created the simulation above; just a voronoi fractured thin box with some random velocities set on it.

## Setting up the initial sim

The first part of this setup it to find a way of knowing when a piece should be fracturing again. The obvious would be to have it based on impacts. So that’s what we are going to do.
Inside the DOP network of our simulation I’m adding a multi solver and a sop solver like so:

If we dive into the SOP Solver we can see that the second input is already set-up to give us the impact data. When inspecting the geometry spreadsheet, you can see that there is a point attribute on the impact data called “primnum”, this makes it possible for us to identify which piece had an impact. The other two attributes of interest is “time” and “impulse”. So what I’m doing to get this data across to my simulation geo is the Attribute Copy SOP. First, however, I renamed the primnum attribude to id, and use that as my attribute to match on the Attribute Copy SOP.

Next thing of this setup is that I want to keep several of this values stored on my geometry, so that I can base the secondary fracturing only on the high impacts, or whatever else logic I make later. To do this I put all the values into two arrays. One for impacts, another one for times. To protect myself from getting too much data, and making the simulation too heavy, I limit the array to only store the first 10 impacts per pieces. The resulting wrangle code looks like this:

float _imp = point(1,”impulse”,@ptnum);
float _tim = point(1,”time”,@ptnum);
float hits = len(f[]@impulses);
if(_imp>0 && hits<10){
push(f[]@impulses,_imp);
push(f[]@hit_times,_tim);
}

## Fracturing again, and applying the motion of the initial sim

Back in SOPs land, the next thing I want to do is to have a look at my impact data. I don’t really need this data to change every frame, so I put down a Time Shift SOP and set it to the last frame, as this will have all the data I need. Considering that I only store the first 10 impacts, this most likely all occur way before the last frame, but it doesn’t really matter in this case. However, if you are doing a heavier initial sim,with more pieces etc., this would be a good place to cache out the sim to disk before proceeding.

After my frame hold, I put another wrangle node. In this one I find the max impulse value, and it corresponding time value. I then store that value into a new attribute which I name triggerTime. This is then attribute copied back onto my initial sim.
The code looks like this:

float maxImpulse = max(f[]@impulses);
int index = find(f[]@impulses,maxImpulse);
f@triggerTime = f[]@hit_times[index];

This is then fed into the second input, the template points input, of a Transform Pieces SOP.
But before doing that, I’m doing some corrections to my transform attributes, using the technique that Matt Estela explains in his wondergul cgwiki: http://www.tokeru.com/cgwiki/index.php?title=HoudiniDops#RBD_extract_correct_transform_attributes

The wrangle code looks as follows:

matrix m4 = primintrinsic(0,’packedfulltransform’,@ptnum);
matrix3 m3 = matrix3(m4);
@orient = quaternion(m3);
@scale = cracktransform(0,0,2,0,m4);
v@pivot = primintrinsic(0,’pivot’,@ptnum);

Now that we have everything setup to apply the motion, we will do another round of fracturing. So going all the way up to my initial fracturing I branch out and make a For-Each Loop.

In there, I do exactly the same thing as my initial fracturing. Each piece gets fractured into another 10 pieces. The only thing of interest here is that under the Attributes tab, i change the Name Prefix to refer to the name of the initial piece. This way the resulting name values has a logical hierarchy, so that you can easily identify the “parent” of each new piece.

The next few steps could be slightly confusing, but bare with me. First I pack all my pieces with an Assemble SOP (with “Create Name Attribute” unticked!). Then, since I know the Transform Pieces SOP will apply the motion of the initial sim by matching the name attributes of both inputs, I need to come up with a way of “hiding” the names of my secondary fracture. To do this, I first fetch the name of the initial piece. I do it in a wrangle one-liner like so:
s@name = prim(1,”name”,0);

Next I put down a Pack SOP, which I set to “Create Packed Fragment”. That’s it. We now have our secondary fracture, and when we plug this into the first input of the Transform Pieces SOP we should see it all working fine. The only thing I change on the Transform Pieces SOP itself is to tick “Copy Tempalte Attribute”, and then I set the attribute to copy to triggerTime, the attribute we made earlier.

## The second sim

Almost there now. After the Transform Pieces SOP, I want to get my secondary pieces back into play, so I put down a Unpack SOP. Make sure to set it to transfer the triggerTime attribute.

Almost done now. The last  thing we need to do is to setup the attributes that will be used by the second RBD sim to determine when our new pieces should be activated. To do this I put down a wrangle node and make the following logic. If the current time is equal or higher than the triggerTime value, the piece should become active, and no longer be animated. Else(if time is less than the triggerTime value, I set active to 0 and animated to 1. This way it will keep its original movement.
Code:
if(@Time>=@triggerTime){
i@active = 1;
i@animated = 0;

}
else{
i@active = 0;
i@animated = 1;
}

Now all we have left do is to set up our second DOP net, and dive inside.
You should be careful to set things up the same way we did in our initial sim here. Meaning that we have the same collision objects and so on. In this setup I simply copy-pasted all the nodes from the initial sim (minus the multi solver and sop solver).

When that’s done all you need to do is to tick “Overwrite Attribute from SOP”, and set it to “active animated”.

And we are done!
If everything went as planned, you should have a working setup for secondary fracturing now. I might develop this further to make the activation of the new pieces to be a bit more sophisticated. Inheriting velocities from the initial sim and so on, but for now this will do!