- Signal Flow and Limitations of Transmission Bandwidth
- Building modules to automate signal distribution and division
- Containers for Display Arrangements
- The Crop TOP
- Modular approaches large playback networks
I love me some referencing. The more you work with TouchDesigner, the more you’ll find that you need a solid understanding of how referencing connects the various parts of your network. Better still is getting a better handle on how Python scripting works in TouchDesigner – especially dot notation. At the heart of what we’re after is making sure that our networks can start to feel a little more interconnected. Hard coding values makes for tedious programming, especially if you’re building something you’d like to reuse. By starting to think about how to build some logic into the system we’re making we begin to build reusable tools. If you’re still getting a handle on how referencing works, then it’s a good idea to get started here (Understanding Referencing) to get your bearings.
Let’s start with a simple example. I’ve got five images that I’d like to cycle through when I click a button. I know that I can use a Count CHOP and a Switch TOP to help with this but how can I make it so that my Count CHOP knows when I add another input to my Switch TOP? In a perfect world I could add or remove images or movies, and the network would just “know” what was going on, right? So how can we program something like this? Let’s start by taking a moment to visit my favorite part of working with TouchDesigner, the wiki. Specifically we need to look at our Switch TOP’s page.
The most important part of this page for us today is here at the top where it says “switchTOP_Class” next to the Python symbol. In object-oriented programming a class is a kind of “extensible template for creating objects.” The exciting part of knowing this is that a class comes with all sorts of methods and values that we can quickly call when scripting. With that in mind let’s take a closer look at the Switch TOP Class page. At this point you’re either beside yourself with excitement, or weeping with confusion. Let’s take a look at a quick example, and see if we can make some sense out of what we’re reading.
One of the first things on the Switch TOP Class page is a sentence that says “This class inherits from the TOP class.” This means that there are several things that work for the Switch TOP that also work for all TOPs. This means we can practice on a regular movie in TOP, and what we learn should also work for our Switch TOP. Okay, let’s open up a new network in TouchDesigner, and let’s add a movie in TOP and a Text DAT. We’ll also need to open up our Textport.
When you open your textport you should see a floating window that looks like this:
In our Text DAT we’re going to write a very simple little script that’s going to print in our textport. In Python we can print something to the textport with the command print(). Whatever we put in the parenthesis gets printed to the textport. You can practice this in the textport, just make sure that you use quotes around your text. For example:
We can also complete this same operation using our text DAT. In the text DAT write:
Now right click on the DAT, and select “Run Script” from the drop down menu. You should see the text appear in your textport:
Congratulations, you just ran a Python Script from a Text DAT. We’re going to use our ability to print to the textport to learn a few more things about our TOP class. We should still have a Movie In TOP in our network. My Movie In TOP is called “moviein1”, knowing the name of our operators is how we call point to them when we’re referencing. Looking back to the general TOP Class Wiki Page, I can see that there’s a member called width and one called height.
For this next step we’re going to use dot notation to get to the width and height information about our operator. For example, I can get that information by starting with the operator name, followed by a dot, followed by the member I want:
Let’s copy that exact line of code into our Text DAT. Next right click, and select Run Script. Nothing happened… what gives?! In this case, just because we asked for that value, doesn’t mean that TouchDesigner knew that we wanted it to be printed to the text port. In order to see these values in the textport we need to encapsulate our script in the print command. When you do this, you should have a script that looks like this:
Now if you run the script you should see:
Let’s try one more. Let’s add one more line of code:
Let’s run the script one more time and you should have something that looks like this:
Believe it or not, we just made some huge progress. Understanding how dot notation works gives you access to a HUGE treasure trove of information that you can use when scripting or writing references.
Let’s return to our example and see if we can’t use what we’ve just learned. Let’s start by adding a few things to our network. I’m going to add five Text TOPs, and I’m going to set them to be the numbers 1 – 5. Next I’m going to wire all of those to a Switch TOP, and then finally to a Null TOP,
Now let’s add a Text DAT to our network, and then take a quick moment to go back to our Switch TOP Class Page. Of particular interest to me is the Connections subsection:
Using what we just learned, write the following script into your text DAT:
When you run this script you should see something like this:
Well, that doesn’t look useful at all, does it? In fact, it’s tremendously useful! Python uses lists to store information, and what we’ve printed out is a list of connections to the Switch TOP. We don’t really want all of this information that we’re getting about the inputs, we just want to know how many connections there are. As luck would have it, there’s a way to get just that information. In Python we can ask for the length (the number of entries) of a list with the len() command. Alright, let’s make a quick change to our script and add the length command. You should have a script now that looks like this:
When you run the script you should see this:
Alright! Now we can start to really make some magic happen. Using .inputs and the len() command we’re able to now see the number of connections to our switch TOP. If you disconnect one of the inputs and run the command again you’ll see the number go down. Add a few more inputs, run the command, and you’ll see the number go up.
How do we use this? Okay, well let’s think back to where we started. We want to use a button to toggle through all of our inputs, and then cycle back to the front of the line. Let’s add a Button component to our Network, and a Count CHOP. Make sure to wire the Button to the top most input on the Count CHOP:
Let’s also make sure that the button is set to momentary:
Looking at our Count CHOP we want to set the Limit Method to “Loop Min/Max.” For the Limit Maximum value we’re going to use the script that we just wrote (only without the print command). We’re also going to subtract 1 from that number. We do this because 0 is still a valid input number for our switch, so while there are five total inputs those are associated with the numbers 0 1 2 3 4. The reference in the Limit Maximum field should look like this:
len(op(‘switch1’).inputs) – 1
Your Count CHOP parameters dialog should look something like this:
And now we have a little bit of black magic happening. If you add more inputs to your switch you’ll see the Limit Maximum number go up automatically, remove some inputs, and you’ll see it go down. Clicking on the button should cycle you through all of the inputs:
Now you know a little more about referencing, dot notation, and how to find more information in the wiki. Happy programming!
Check out the TOE file if you’d like to see what I made: Referencing Part 2
If you spend much time programming in TouchDesigner, eventually you’ll want to start doing some real-time rendering. When dealing with rendering some 3D geometry we need to get a few pieces of our network correctly set-up to get started. There are, of course, lots of different methods for rendering but we can get started with some rendering basics.
Like working in any rendering environment, we need a few things in place to actually draw an image. We need to have the actual object that we want to draw, we need a light source (not always, but for now let’s pretend), and we need to know where we are looking at the scene from. In TouchDesigner we can think of these elements in the following way:
Geometry Component – this is our object that we’re drawing. This component holds a Surface Operator (SOP), that is the object we are drawing.
Camera Component – this is the vantage point we are drawing out scene from.
Light Component – this is our light source for our scene. There are some cases where we don’t need a light, but it’s a good rule of thumb to assume that you’ll need to light your scene.
Render TOP – this texture operator is the drawing / video that is the result of your render set-up. This is the TOP that you’ll end up using in your network / performance / etc.
Using these three components and one operator, we end up with a basic network set-up that looks something like this:
At this point you’re probably familiar with patch cords (called wires in TouchDesigner’s official documentation) that connect operators within a single family (CHOPs, TOPs, SOPs, DATs, etc), but you may not be as familiar with the dotted lines with arrows that you see in the image above. These are called data links, and their visibility can be toggled on and off with the short cut key “x”. Unlike wires, data links help us see when operators from different families are connected in some way. We can also see if data is actively being passed through these connections – if the arrow head is moving, then new information is being passed, static arrows tell us that we’re not actively passing new data.
Let’s take a look at a quick example – here we can see that the Geo is constantly sending information to the render TOP. When we change the position of the camera Comp, we can see the arrow heads move. While this might not seem like something worth caring about in this very moment, there will surely come a day when you’re debugging a scene and the ability to quickly see what’s passing new data and what’s not will be the blessing that helps you keep your sanity.
Let’s take a moment to give our Render TOP a closer look. The Render TOP has five different pages of parameters, and while all of them are important we can start by looking at the Render Page and the Common Page.
The Render page contains all of the information about what components we’re currently using. Here we can see that we’re using cam1 as our Camera, * as our Geometry, and * as our Lights. What is this gibberish? Our Render TOP follows many of the pattern matching rules as the rest of TouchDesigner. In this case a * means, “any geometry component.” You can test this by adding another geo to your scene. You’ll see another set of data link lines drawn to the Render TOP, but you won’t see another torus. Why? Well, you won’t see another Torus because it’s being drawn in exactly the same dimensions in the same place.
At this point you could tell your Render TOP which Geo to use by typing in the name of the Geo component. For example, if we write “geo1” in our Geometry Field we’ll only see data links drawn from geo1 to our Render TOP.
Why do we care about this? This is useful as it has large scale implications for lots of different rendering situations – advanced lighting, camera actions, etc. This also gives you a way to divvy up rendering between TOPs and composite the video later.
In addition to the Render Page, we should also take a moment to look at the Common Page.
On the common page we can specify the resolution of our final image, as well as a few other parameters. Rendering can be a very GPU heavy task, so keeping an eye on your rendering resolution can be extremely helpful in managing the performance of your network. Alright, with all of that general information out of the way, let’s make something with our new found knowledge. Let’s start by rendering a simple sphere.
We can begin by opening up an empty network and adding a Camera COMP, a Geometry COMP, a Light COMP, and a Render TOP. This should now be looking very familiar.
This, however, is not a sphere… this is a Torus, so how do we change what we’re drawing? To do that we need to look inside of our Geometry Component. Using either the quick key or the zoom method let’s take a look inside of our Geo.
Here inside of our Geometry is just a single lonely torus. We should also notice that the display and render flags for this SOP are turned on. What we can learn from what we’re seeing here is that whatever is in the Geo Component with a render flag (purple) turned on will be used when rendering our scene. As a note about efficiency, we can technically render any SOP without placing it inside of a Geometry COMP. The difference is that SOPs located in a TouchDesigner network outside of a Geo are rendered on the CPU, while SOPs inside of a Geo are rendered on the GPU. Generally, the most efficient use of your system’s resources is going to be achieved by making sure that you’re taking as much advantage of your GPU as possible.
Inside of our Geo lets make a few changes. We can start by deleting the Torus SOP. Next lets add a Sphere SOP, a Box SOP, and a Null SOP. For now lets wire the Sphere SOP to the Null, and turn on the display and render flags for the Null as well. When you’re done you should have something that looks like this:
Now if we zoom out of our Geo we can see that we’re rendering a Sphere instead of a Torus.
Suppose that we want to see the box instead? To do that we would zoom inside of the Geo, and wire the Box to the Null instead of the Sphere. This is a prime example of how the use of a Null can be powerful in programming in TouchDeigner. If our geometry chain was much more complicated, or if we wanted to further change our source Surface Operator we could make all of those changes up steam of the Null. Practically this would mean that all of the alterations that were made did not require any changes in order to be targeted for rendering. Let’s take a look at how this might work using a single Null. First let’s add a Merge SOP to our chain, we’ll wire both the Box SOP and the Sphere SOP the Merge, and then wire the Merge to the Null. When we’re done we should have something that looks like this:
Well, surely something has gone wrong, right? No. Things are just as they’re supposed to be, it just happens that our Box in currently located inside of our Sphere. Let’s change the origin position of our Sphere and our Box so they’re not overlapping. To do this lets start with our Sphere. Clicking on the Sphere SOP let’s start by changing its radius to 0.5 for x y and z, and changing its center to -1 0 0.
Next let’s change the origin of our Box to 1 0 0.
Now we should be seeing something like this:
Alright. Now let’s back out of our Geo.
Excellent. Now we’re getting somewhere. Okay. This is all well and good, but what if I want to have different kinds of materials associated with my Geometry? Our last stop on looking at what we can do with our Geometry Component is going to be materials. Let’s click on our Geo and look at the Render Page. Here you’ll notice that you can assign a material to your geo.
You can assign a material to a geo by dragging and dropping it onto the geo, or by typing the name of the material into the Material Field. Let’s start by assigning our Phong1 to our geo1.
Well, that’s a subtle change. A Phong shader comes along with some lovely tools for shaded and more realistic rendering. That’s a topic all to itself, so for now let’s just look at how we can change the color of our Phong. On the RGB page of our Phong let’s click on the diffuse swatch, and change our color.
You’ll notice here that it’s changed the color of both our Box and our Sphere. The material that we apply to our Geo will be allied to all of the contents of our component. We can definitely apply different materials to different portions of our geo, but we’ll talk about that another day. If you’re feeling adventurous take some time to play with some of the different settings here in the Phong Mat.
Next let’s look at what happens when we apply the Constant.
Here we can see that the constant applies a single color to the whole surface of our Geo. It’s worth noting that at this point that we don’t need a Light Component when using a constant as a material. Unlike a Phong which uses a light source when rendering, the constant just emits constant color. Just like the Phong, we can also change the color of our constant. Let’s take a moment to try that out. Just like with the Phong you’ll click on the Constant, and look at the Constant Page:
Alright, now it’s time to look at what happens when we apply the Wireframe to our Geo.
The wireframe, like the constant, does not require a light in the scene to be rendered. In my opinion, some of the most interesting work comes out of mixed materials in rendering – combining phongs and constants, phongs and wireframes, et cetera. You’ll remember that back when we were putting our scene together we merged our Sphere and our Box. The diagonal line connecting them in the wireframe illustrates how they’re still connected. Before we leave the wireframe material let’s change just a few things. Like with our Phong and Constant, we can change the color. We can also change the thickness of the line. Let’s take a closer look at the Wireframe Page of the parameters and make some changes.
Let’s take a quick look at what our Camera can do for us. First, I’m going to switch back to the Phong as a material. In our Camera settings let’s move back slightly, and set our z rotation to me.time.absFrame.
Manipulating our camera changes our relationship to the geo in our scene, giving us the ability to shift our perspective. We can further alter this relationship by adding a Null Comp to our scene. After we add the Null Comp let’s tell our Camera Comp to look at the Null. We can do this by typing in the name of the Null in the Look At field in the Xform page of the Camera’s parameters:
Okay, so why do this? Well, before when we altered our camera’s location it was only pointed straight ahead. By adding a null for the camera to look at, we now have a focal point that we can manipulate. This is especially apparent if we translate our camera in either the x or y dimensions. Even thought the camera is moving left / right or up / down, it still stays pointed at our sphere and box.
Alright, let’s wrap this up by quickly looking at what our lighting has to offer us. Like all of the other Components we’ve looked at in this post, we are just scratching the surface of what’s possible. This look at rendering is intended just to get you started on the basics. Lets start by looking in the Light page of the Light’s Parameters.
Take some time to play with the color and dimmer settings the light to get started. When you’ve got a sense of how those work, the next attribute to take a closer look at is the Light Type. I’m going to change color of my light to a soft mauve, the light type to cone, and the cone angle to 8.
Now that you have a rough idea of what goes into rendering a scene in TouchDesigner, it’s your turn to play and discover. Happy real-time rendering. Want to see what I made, look at the Rendering TOE File.
Referencing is one of the most powerful tools at the programmer’s disposal in TouchDesigner. Referencing creates a direct link between two or more floats or integers. This allows you to link operators that are outside of their respective families – normally you can only connect CHOPs to CHOPs and TOPs to TOPs, but referencing allows you to create connections between nearly any operators. There are a number of way to create these links with references or expressions. In many of the other posts that I’ve written I often write about using expressions and references, but haven’t taken much time to talk in depth about what this is, how how it all works. Let’s change that.
I started thinking about this when I saw a post on the Derivative forum from a new user struggling with understanding what I’d written in some earlier tutorials. Expressions are something that I continue to learn more about, and open up all sorts of opportunities for faster, more streamlined, and more elegant programming. Let’s start by looking at the typical kinds of referencing that you might do on any project. Specifically, let’s look at how we might connect one family of operators to another. In this example we’ll look at connecting a CHOP to a TOP, and all of the different ways we might do that.
In the image above we actually are referencing the same CHOP in four different ways. We can start this by first talking about how we connect two operators from different families. In this example I’m going to use a noise CHOP and a circle TOP. I want to use the sudo random noise from the noise CHOP to drive the vertical position of my circle in my circle TOP. There are a two major ways that we can make this connection: dragging and dropping the CHOP onto the TOP, or writing an expression that connects the two of them. I often opt for writing the expression – I do this because I think it’s good practice, and has helped me better understand the syntax and structure of using expression in references. We’ll take a look at both of these methods.
Let’s start with the drag and drop method. To use the drag and drop method we need the source operator to be viewer active (there are some exceptions, but it’s a good rule of thumb that your source probably needs to be viewer active to do this). We can make an operator viewer active by clicking on the + symbol in the bottom right corner, or by holding down the alt key (holding alt will make all operators viewer active). You can tell an operator is viewer active because the color coded border disappears, and usually a portion of it is highlighted when you mouse over the operator.
Let’s take a moment to better understand the anatomy of an operator while we have this example handy. On the left upper corner of the operator we have a few different toggle switches – viewer, clone immune, bypass, and lock. Along the very bottom of our operator we have it’s name (you can make changes to this field), any flags associated with the operator family, and the viewer active toggle. Having a solid sense of the anatomy of your operators becomes increasingly important the longer you work with TouchDesigner.
Alright, now that we know how to toggle our viewer active mode on and off, and know a little more about our operators’ anatomy lets look at how to build a reference. Let’s make a noise CHOP in our network as well as a Circle TOP. With the Noise CHOP viewer active, click on the name “chan1” in the viewer, and drag it to the Y parameter of the Circle TOP (I’ve made my circle a little smaller, to make this easier to see):
As you do this you should see a drop down menu appear, let’s select “Export CHOP” from the list. You should now see the Y position (or center 2) changed to a green color. You should also see some text that shows up as well. Here’s a closer look at just the paramater we’ve changed in the circle TOP:
Looking closer we can see that the text reads: noise_active:chan1. Great, but what does that mean?! Well, if we take a closer look at our Noise CHOP we can see that I changed the name of that operator to “noise_active” – we also see that the name of our noise channel is “chan1”. If we were to abstract what we’re seeing in the export language we might write something like this:
Exporting is a fine way to connect operators, but it’s not my personal favorite. I say this because exporting creates a locked relationship. Once you’ve done this you can’t change the text in the target operator. Exporting creates a much more permanent relationship between your operators. To remove the export you’ll need to right click on the parameter filed and select “remove export.” Surely there’s a better way to connect operators?!
In fact, there are still three more ways to connect operators. Taking a closer look at the drop down menu that appears when we use the drag and drop method we see the following that there are several Methods:
For now we’ll take a pass on the “Text” and “Current CHOP Value” options as these have more limited uses. Let’s now take a close look at our Relative and Absolute Reference options.
Let’s go ahead and make another circle in our network, and this time let’s create a relative reference between our noise CHOP and our circle TOP.
Okay, what does this mean? Lets start by looking at the syntax of this expression. First we can see that we’re looking for an operator. We know this because our expression starts with op(). Next comes the name of the operator in quotation marks. As an important note, Python doesn’t care if you use double quotes or single quotes so long as they match. This means that “noise1” and ‘noise1’ are both equal and produce the same results; ‘noise1″ or “noise1′ however will not work. Finally we see the name of the channel in question in brackets and in quotes – [“chan1”]. This means that our syntax looks something like operator(“exact_name_of_operator”)[“desired_channel”]. Okay, let’s look at another example to make sure we have a firm understanding of how relative referencing works.
Let’s make a Constant CHOP. Let’s name change the name of the constant to “fruits” and name the first three channels, “apple” “pear” and “lemon”. You should have something that looks like this:
Alright, now lets add a circle TOP to our network. This time, instead of using the drag and drop method we’ll write out the Python expression to create a reference to our constant. We’ll start by referencing our apple channel. This means our expression is going to be:
You can write this directly in the expression directly in the target parameter field for the target operator. When you’re done you should have something like this:
If you drag the slider in the constant CHOP to the right, you should now see the circle move up in the viewer. So we’ve successfully connected our circle TOP to the apple channel, why is this any better than just exporting? Well, let’s say that for whatever reason you change your mind while you’re programming and decide that instead you’d prefer for the circle TOP to be connected to the “pear” channel? Written as an expression we can make that change simply by deleting “apple” and replacing it with “pear” or “lemon”. Our expressions then would be:
Additionally, if we’ve written a reference as an expression we write some math directly into our reference. We might, for example, only want half of the value coming out of the apple channel. In this case we’d write the expression:
op(‘fruits’)[‘apple’] * 0.5
This would divide ever value in half, changing our scaling from 0 – 1 to 0 – 0.5 instead. We can also use this method to multiply a channel by another channel. For example maybe we want to create a relationship between two different channels from our fruits constant. We might write the expression:
op(‘fruits’)[‘apple’] * op(‘fruits’)[‘lemon’]
You could just as easily do this with a Math CHOP, but you might find that just writing the expression is faster, simpler, or more tidy.
Before we move on, there are two more modifiers that we need to know when writing relative references:
What on earth are these all about? Well, these are handy directory pointers. At some point you will surely end up wanting to reference an operator that is another part of your network – a control panel, a material, a slider, you name it – if you program in Touch long enough, you’re gonna need these. So what do they mean:
./ – this modifier means the network inside of me
../ – this modifier means in the network above me
If you’re scratching your head, that’s okay. Let’s look at an example. Let’s say that we have a Geometry component, and inside of it we have placed a material – a constant that’s red. A relative reference for that material would be “./constant1”. This means, look inside of me for the material called “constant1”.
Here’s what that would look like:
Now that we understand what relative references are, what are absolute References? Unlike relative references, absolute references require the entire network path to an operator. In the case of our noise and circle example, that means that our reference looks like this:
Absolute references require that you know exactly where in your network you’re referencing an operator from, because you have to use the entire network path. That sounds like a pain, so why use them? Well, let’s imagine that you’re building a complex program and you’re trying to be as tidy and organized as possible. You might build a large change of your user interface in a single location. This means that all of the sliders, buttons, and menus that are being called all live in the same container. In this case, using an absolute reference makes good programming sense. Relative references will leave you constantly trying to figure out how many ../ to use when referencing your user interface. Absolute calls don’t require this, as they point to a very specific place in the network. You can even simplify this by making sure that all of your buttons and sliders are joined with a merge CHOP.
To get a better sense of how this works, download the example .toe file and look at the last example that’s driven by sliders that control the level TOP. There’s lots more to learn about expressions, but practicing your references will help you begin to understand the syntax and logic of how they work.
Download this example toe to learn and explore some more – referencing toe
Working with live streaming data is about as good as it gets when it comes to programming – this is especially true if you’re working on a project that looks to create a recognizable relationship between live data and media. What, then, is a person to do when placed in a situation without access to a live source of data? Whatever the project, the best way to tackle this problem is to find a source of prerecorded information. If you’re working on something like motion tracking, using a pre-recorded video is an excellent solution to this problem. What about sensors that aren’t image based? What if I’m dealing with a series of floats? What happens if those floats just come to me in a table? How can I take a series of recorded data points that live in an text file and make them move? That’s exactly one of the problems that came up for me recently, and I’ve got a handy trick that will make it easy to work with a data set in a table as though it were streaming into your TouchDesigner network live.
To get started, we need a file with some data in it. I made a quick spreadsheet with two columns. One starts at 0.01 and goes up to 1, awhile the other column starts at .99 and counts down to 0. If you’re following along, you can download that text file here (tabledata). In broad terms, what were going to make is a simple network of operators that moves through a table, pulling one row of data at a time, and then converting that table information into CHOP data. We can see where we’re headed if we look at our whole completed network:
So what’s happening here? In the DAT called “data” we have a table of recorded values. Next I use a select to remove the header row from the data, and another select to move through the rows of data. Using another table, a transpose, and a merge gives us a table that’s easy to convert into a CHOP. Now that we have a general sense of what’s happening in this network, let’s dig-in and get to work.
We’ll start by adding a Table DAT to an empty network. Rather than entering data by hand, we can instead just point TouchDesigner to a file that we want it to use. In the Table DAT’s parameters dialogue we’ll click on the plus button to the right of the “file” field and then locate the file that we’re looking to use.
In order to see our table data we need to click on the button “Reload File” so that our table will be populated with the information from the file that we’re using. Next we’re going to use a few Select DATs to manipulate the contents of our table. We’re going to use the first select to remove the header row of our table. To set this up, we’ll set our select to extract rows by index, starting at 1.
You’ll also notice that specifying that we’re extracting rows by index turns on a End Row Index value that’s driven by an expression (me.inputs.numRows – 1). We’re going to use the logic from this expression a little later on, so tuck that into the back of your mind for just a moment.
Next we’ll use another Select Table to move through the rows of our table. In adding another Select, let’s again set it up to extract Rows by Index. This time, however, we’re going to change the value of the start row and end row index to be the same. Doing things, you should notice that we get only one row of our table. Try changing the values of these parameters – as long as both fields contain the same number you’ll see only one row of information. We’ll animate that in just a moment taking advantage of this.
The next operator that we’ll add to this network is a Transpose DAT. A transpose will change rows into columns, giving us a result that’s two rows, rather than two columns of data.
While just these changing values are ultimately what I’m after, I would also like my values to have names. To do this I’m going to add another table DAT, creating two rows: xPos and yPos. I’m going to use a Merge DAT to combine these two tables – to make this work properly we’ll need to set the Merge to append columns. When we’re doing we should have something that looks like this:
Alright, not that we have our DAT string’s set up, let’s animate this table, and look at how to get some CHOP data out of these DATs. First let’s start by adding a Constant CHOP to our network. Let’s give our first channel a useful name, and then call our absolute frame count (me.time.absFrame).
Why use absolute frame? I’d like a steadily increasing integer that can be used to drive our progression through the rows of our table. Our absolute frame is an excellent candidate for this need – except that I don’t want to exceed the maximum number of rows in my table. To do this let’s add a Limit CHOP. First up I’ll need to set this Operator to Loop, I’ll also want to set this operator to start at 0 (Minimum).
For the maximum value, I want to use the total number of rows in our second table (the table that contained only data, without a header). I could hard-code this by entering 200 into the Maximum parameter of our Limit, but then I have to change this number whenever my table changes. A better solution would be to use an expression to pull this number from the table in question – which is exactly what that expression we saw earlier does. The expression we want to use then for our Maximum parameter is: op(‘select1’).numRows.
Now it’s the moment we’ve been waiting for. Lets make that table move! To do this we’ll use the row counter in to drive our location in our table – we’ll write some relative references in our select2 DAT to make this happen. In the Start Row and End Row Index values let’s use the reference op(‘limit1’)[‘row’] to drive the change in our table.
The last step here is to add a DAT to CHOP to our network. We’ll add this at the end of our network, and drag the target DAT onto the CHOP.
There we have it. We’ve just taken a static table full of data, and turned it into a channel data that changes over time. For extra credit, add a Trail CHOP to the DAT to see what your data looks like.