TouchDesigner CHOP Tongue Twisters
TouchDesigner is one of the most powerful softwares around in the field of interactive technology and immersive media. The amount of different inputs and outputs that TouchDesigner can handle is out of this world. But that doesn’t mean all of it comes easily, especially if you’re coming from other software packages or programming languages. You might find yourself more frustrated than fulfilled. Don’t give up! A little bit of perseverance and a little bit of familiarity with TouchDesigner idiosyncrasies will take you a long way. In this post, I wanted to talk about one specific concept that seem to trip up everyone from beginners to pros: CHOP Data/Shuffling. Let’s dive in!
If you’ve worked with higher skilled TouchDesigner developers, you might have seen them do really complicated looking things with a technique called “shuffling.” Most of the time this is done with the Shuffle CHOP, but we’re going to go a little deeper than just using the Shuffle CHOP. Before we get to shuffling, the important thing to understand is the data structure of CHOPs. New users of TouchDesigner become accustomed to what a typical CHOP looks like:
They see this representation of CHOP data a lot when they’re starting out with basic operators like Button COMPs, Constant CHOPs, Timer CHOPs, etc. Then you might find some operators have more channels to them, but they’re named and easy to follow:
So far so good. Even with more channels, we can still plug this into other operators and everything goes as expected. What starts to become tricky is when we try to work with CHOPs that look like this:
Or even more daunting…:
When I was a beginner and even an intermediate developers, “Yikes,” was my first reaction to seeing that. The daunting part about this is that we don’t really know what it is. Thus it’s important to understand CHOP data structure.
Data in 2D
I explain TouchDesigner CHOPs as holding numeric data in beginner workshops and classes. While this is true, there’s another layer to that because CHOPs can hold data in 2 different dimensions: channels and samples. In the images we had above, we saw examples of both kinds of data, but I find it even more easy to understand when you compare CHOPs to tables. You can think of channels as rows and samples as columns. For example, a CHOP with 10 channels and a length of 1 sample is equivalent to a Table DAT with 10 rows and 1 column:
Similarly, you can swap your rows and samples, so a CHOP with 1 channel and a length of 10 samples would be equivalent to a Table DAT with 1 row and 10 columns:
Our daunting examples from the previous section aren’t anything to fear, they were just a combination of both the above examples and they had both multiple channels and multiple samples, just like any other table we might be used to dealing with. I don’t know many TouchDesigner developers who are afraid of tables, so we shouldn’t be afraid of hectic looking CHOPs. In the example below, both the table and CHOP are equivalent:
Why do we shuffle?
Now that you have a better handle on CHOP data structures, we can look at shuffling. Shuffling in TouchDesigner is the way we move between channels and samples. Nothing more, nothing less. You can even think about it like transposing tables, when you flip the rows and columns (like a Transpose DAT), but with a lot more flexibility. A good example is that we can move between our examples above and back using a Shuffle CHOP set to Swap Channels and Samples:
But why would we even shuffle to begin with? It seems like such a strange thing to want to do. One of the reasons is that certain CHOPs can only operate on certain types of data. For example, a Logic CHOP can operate on a lot of channels but only with a length of 1 sample. If you had the data from the second operator above and you wanted to pass it to a Logic CHOP to process the data further, you would have to use a Shuffle CHOP to transpose your data from 1-channel-with-10-samples to 10-channels-with-1-sample.
An example of the opposite would be geometry instancing. When you’re feeding a Geometry COMP with CHOP channels for instancing, you have to create a new sample per instance. You will usually have only a few predefined channels, such as tx, ty, and tz, and then you’ll continuously add samples for each new instance you want to create:
Finally, a more unique usage of shuffling is to flatten 2D CHOP data instead a single dimension for further processing or instancing. In the example below, a TOP to CHOP is used to get the noise values from a Noise TOP and convert them into CHOP channels. This leaves us with one channel of value per row of our texture and one sample per column. Since we’re instancing, we need everything to eventually collapse into the 1-channel-many-samples structure we mentioned above. We can use a Shuffle CHOP with the mode set to Sequence All Channels to join each channel one after another (which coincidentally is how our Grid SOP also orders its points!) and prepare it to be fed into the instancing setup:
Beginner TouchDesigner solutions
So with all that said, where does that leave you and in particular where does that leave beginners/intermediate TouchDesigner developers who have trouble working with two dimensional CHOP data? One trick anyone can use is to isolate and shuffle! This method works on almost any kind of data and can work in either direction like we mentioned above. Take a look at the example below, we have some CHOP data that might be a little bit more than we would like to deal with at the moment:
The strategy for isolating is to use a Select CHOP to pick out the one channel you might be interested in. The strategy for shuffling is to then turn that data into a kind of data you’re more comfortable with or the kind of data that you require for your particular usage. You can also rinse and repeat this strategy, since it is pretty efficient, to shuffle in/out a lot of data like in the example below:
From there, you can work with your data as you need and then when it becomes time to export or reference the data, you know that all of channels are still aligned, so the first channel of all your shuffled out operators are the first sample from the original data, all of the second channels are the second samples, etc etc.
The same can be done in reverse if you have a bunch of control channels or values that you want to then use for instancing or similar. You can take them all individually, use a Merge CHOP to turn them into a multi-channel-single-sample structure, and then use a Shuffle CHOP set to Swap Channels and Samples to get it ready for the final destination:
With all that said, what are the main takeaways here for TouchDesigner developers? CHOPs can be thought of as 2D data. Shuffling CHOP data is like transposing data but with more flexibility and uses. You can simplify complex data structures with Select CHOPs and Shuffle CHOPs. You can combine simpler data by using Merge CHOP and Shuffle CHOP. Phew! There’s a lot. At the end of the day, hopefully this sheds a little bit of light on shuffling CHOP data in TouchDesigner. By knowing the deeper reasons of why/how/what for, you should be able to look at more complex networks and figure out what is going on without trying to decipher the Voynich manuscripts!