I recently wanted to create a spring model in houdini and found that neither the copy node, nor the poly extrude tool in themselves made this easy.
In the end, using a combination of the copy node, poly bridge, and most imporatantly the ‘for’ node does the job well.
What didn’t work
The copy node lets us specify how many copies we want to make, as well as how to translate and rotate each new copy. If we were to simply place down a circle and then use the copy node to create a spring pattern, but we would need to be able to connect each individual circle to form a solid spring shape. I.e. something like this:
Unfortunately, the copy node in itself does not have a way to connect the faces together. If it did, we could just check that box and call it a day.
I also considered an approach where I created a circle, copied it with a translation and rotated it so that I have 2 along the path of a spring, then use PolyBridge to create the first bit of the spring. Then tried to use a copy node to simply create many copies of this spring with translation and rotation. Unfortunately, the copy node in this case would create a bunch of disjoint pieces since the rotation between the copied pieces was off. I would get something like this:
In the end, what worked for me was using polybridge once for every pair of adjacent circles (opposed to using just 1 polybridge and copying that). It’s not feasible to do this by hand (Though i’m certain someone out there has done it).
What we’re going to do is this:
- Create a copy node which creates exactly 1 more circle based off the original circle.
- Use a PolyBridge node to connect the original circle to the new copied circle.
- Repeat step 1, except this time we set the ‘original’ circle to be the newly copied circle.
We will use the ‘For’ node to have the ability to repeat ourselves.
Using the for node in this case will involve some management of groups to determine what the current circle is.
I will start from the top now that I have given an overview of how this is done. Also note that I’m using Houdini 15.5 for this.
Place a circle down
Add this single circle to a group
This group will at all times represent our ‘newest’ circle.
Let’s call this thing ‘copyGroup1’.
The copy node we use later can be configured to output groups for the copied primitive, we will make sure that it outputs the group name as ‘copyGroup1’. We will use this group to represent the newest circle primitive. At first we create it manually, but every time after the copy node will augment our group to contain the newest circle primitive.
Add in the ‘For’ node
Doesn’t need any special configuration. The end node of the for contains the number of iterations to do. I recommend you keep this at 10 at first. If there’s a mistake in your loop, you can quickly put yourself in a loop that makes houdini do some serious cooking.
We will be adding all further nodes in between the ‘start’ and the ‘end nodes of the For.
Add a copy node in the For loop.
There are a few things we need to do to configure this copy node.
- Add a bit of translation away from the current circle, both in the x and the y.
- Add a bit of rotation to cause the circles to eventually spiral. Make sure to set your pivot as well (That will represent the center of the spring).
- Set the source group to be copyGroup1. Think of this as meaning we want to copy the ‘newest’ circle primitive. We will make sure that copyGroup1 at all times refers to the newest circle.
- Set the copy node to make ‘2’ copies. (This means make 1 actual copy…)
- Check the ‘create output groups box’ and uncheck the ‘preserve groups’ box.
- Make the group naming template to be: copyGroup`
This will make sure that the newly created circle will be placed into copyGroup1.
Adjust copyGroup1 to contain *only* the newest circle
After the copy node the new circle primitive is added into copyGroup1. Let’s just add a group node which adjusts copyGroup1 to just contain everything that’s not in copyGroup0. This will make copyGroup1 *just* contain the newest circle, and copyGroup0 will be the previous circle. This will make using the PolyBridge node easier.
Add a group node (i’ll name this name copyGroup_adjust), disable ‘creating’ of a group since this group node will just be editing an existing group.
To remove everything from copyGroup1 that is in copyGroup0, it would look like this:
Add a PolyBridge node
Let’s set the source group to copyGroup0 and the destination group to copyGroup1.
As well, I prefer using divisions = 1 here.
Also, uncheck ‘Reverse winding’.
Add the circle primitives back into the feedback loop
If you notice, the PolyBridge node actually gets rid of the primitives inside of copyGroup0 and copyGroup1. We want to add those back. We’ll at least need the contents of copyGroup1 for every next iteration of the loop. We can add these back into the feedback loop by simply feeding the output of my ‘copyGroup_adjust’ node into ‘repeat_end1’. We’ll need to use a merge node though since we can only have 1 input directly into the end block node.
Add all the PolyBridges back into the feedback loop as well
When we create a PolyBridge we’re passing it into the feedback (end block), but the first thing we’re doing in the loop is the ‘copy’ node which uses copyGroup0 and copyGroup1. This node is immediately erasing the PolyBridge primitives. If we pass the feedback from the input directly into the output, we can keep all our poly bridge primitives between every iteration.
I’m just going to add a connection between the start of the loop and the end of the loop (through the merge node).
There is 1 huge problem though, our connection directly from the input to the output that we just added is augmenting the new value of copyGroup1 with the previous iteration’s copyGroup1.
Let’s wipe out the previous iterations copyGroups before passing that feedback forward. Without this, copyGroup1 will actually grow exponentially as the copy node will be copying multiple circles at a time.
Let’s add a group node which just deletes copyGroup0 and copyGroup1, between the start of a our For begin node and our merge node.
Increase the end node’s iteration count
I recommend increasing this very slowly to make sure that a bug in your loop doesn’t cause Houdini to hang.
After this I have a nice spring that can wind as many times as I like:
If you happen to know of a better way to do this, please let me know in the comments.
Attached is the hip file to this project.