Category Archives: Software

Building a Calibration UI | Software Architecture | TouchDesigner

Here’s our first stop in a series about planning out part of a long term installation’s UI. We’ll focus on looking at the calibration portion of this project, and while that’s not very sexy, it’s something I frequently set up gig after gig – how you get your projection matched to your architecture can be tricky, and if you can take the time to build something reusable it’s well worth the time and effort. In this case we’ll be looking at a five sided room that uses five projectors. In this installation we don’t do any overlapping projection, so edge blending isn’t a part of what we’ll be talking about in this case study.

Big Ideas

Organization Matters

How you build a thing matters. Ask any architect, chef, crafts person, quilter, and on and on and on. The principles and ideas that drive how you’re building your network matter, and as a full disclaimer I am a misery to collaborate with when it comes to messy TouchDesigner networks and messy directories. “As long as it works, it doesn’t matter Matt!” Is the mantra I often hear as a push back to my requests for organized work. There’s a lot of truth in that, but if you ever have to work with another person (or work with your future self) then the organization of your work will matter. Cluttered, messy, or disorganized structures will make a world of misery for you and your collaborators. You can do whatever you want at the end of the day, but my strong recommendation is that you create some guiding principles for your organization structures, network layout, documentation, and pending todo items on a project.

Here are some of my simple suggestions:

Turn off node resizing for TOPs and COMPs, and don’t resize your nodes by hand:

What? Why? Those things might make perfect sense to you, and you might like them a lot – and that’s great. I hate them in my networks because they insert irregularities into the flow of the network that spoof importance. When I look at a network and there is a single node that’s larger, smaller, resized in anyway that’s different from the surrounding nodes  it implies to me that it has some significance or importance. It might well be that you just needed a closer look for a second and then forgot to change its size again, but for the person looking at your code for the first time that it is significant – even if it’s not. Time and again I’ve seen that kind of use of resizing throw off myself, and many of programmers that I respect.

If you need to use size as a defining characteristic in your networks, then use python to make nodes consistent sizes. It all goes back to being organized and consistent. Help your future self, or the other people you’re working with avoid as much confusion as possible… chances are the project is already confusing enough.

resizing

Align your ops:

I like the left bottom corner of my ops aligned with the network grid. I like to start new ops on new grid lines, and I like a full grid line of vertical space between ops. I also like to arrange ops (when possible) so that wires don’t cross unnecessarily. OCD much Matt? Sure, you can say that if you like. For me, the truth of the matter is that I like tidy networks where I can quickly see the flow of operations left to right. Too much space and things feel spread out all over creation, too little space and it can be difficult to see a network’s operation when you’re zoomed out too far. For me, this is the right kind of balance. It might well be different for you, and that’s wonderful. My only encouragement here is to be purposeful. Whatever you do, make sure it’s a choice you’re making not just the happenstance layout that emerged from the creative process. Be messy, be wild, place nodes every which way … but tidy up before you save and commit your work for the day.

alignment

Color code sparingly

I love me some color coding, but make sure it’s done purposefully and give yourself a key. This is another situation where color coding is often a great idea on the face of it, and then it quickly changes into something you can hardly keep track of. That’s okay, and my experience has taught me that less is better in this regard.

Leave those op names alone and only append after the op name

It took a lot to get me on board for this, but it’s now something that I’m whole wholeheartedly behind. Leaving the original operator name in place and only appending after is a tremendous help when it comes to quickly glancing at a network. It helps the viewer know quickly what an operator is doing without having to do any additional inspection.

“I don’t get it Matt.”

That’s okay. Let’s look at this example:

names_nightmare

In 2 seconds or less can you tell if the first operator with the banana is a select or a moviefilein TOP? Can you tell if the composited image is a comp TOP or a multiply TOP? Can you tell if the TOP labeled “done” is a null or an out TOP?

Compare that with:

names

To be fair, the names aren’t nearly as exciting, but they do make it much easier to understand what’s happening at a glance.

Like it or not, you’re an engineer now

As much as we all might like to fancy ourselves Artists with capital letter As and a filigree flourish, the truth is that right now you’re an engineer.  That’s not to say that you’re not an artist too, you are; but some problems don’t need artful solutions, they need thoughtfully engineered solutions based on a complex understanding of computation and computer science. The more you work in TouchDesigner, the more you’ll find that you’re as much engineer as you are artist – that’s not only okay, that’s an important realization to make about your own work. It can be a bifurcating moment to feel at conflict with the art, and the mechanics of a given network – “this approach is beautiful and it works but costs 20 milliseconds” is probably not a viable solution. It’s especially not a viable solution for something like a calibration pipeline that needs to have as little computational overhead as possible. The work that goes into an efficient process isn’t always glamorous, or much to show off; instead, it makes room for the art with a capital A to take more cycles and be more expressive.

Lucky for us, there’s room to be both engineer and artist in our work. Remember to embrace both of those roles, even when faced with the frustration of complex logic problems, or when faced with the questions of aesthetics.

Externalizing Files

So we should externalize files? Yes. For the love of god, yes. If you believe in a world where you don’t tear your hair out, yes. In case you still are wondering, the answer is yes – you should always look for ways to externalize files.

Why? That seems silly.

Once upon a time I didn’t externalize any components, and my projects lived as complete toe files and the world was beautiful. Then I crashed my project because I did something silly, and then it took me hours to track down where the problem was… even opening the crashautosave.toe left me slowly moving through networks in networks trying to figure out what I had done where to make everything crash. Worse yet, because it was just a single toe file there was no way to unit test any of the smaller modules. Open, change, save, open crash… repeat. If you haven’t had this experience yet, it’s only a matter of time.You too will crash one day, and mightily. You’ll wonder why you ever wanted to work with computers in the first place, and why you don’t just open up a bar in on a sandy beach somewhere.

Snark aside, externalizing components in your network has several benefits. For starters, it moves you away from having a single toe file black box that’s difficult to test or debug. Separating out smaller modules allows for more portability between the applications that you build, and it means that you can test just that module. It also means that you can update just that module and not your entire toe file.

Externalizing modules, extensions, and the like also lets you more easily compare files over time if you’re using a piece of version control software – don’t worry, we’ll talk about git in just a second. It also makes it easier to work with text files in something like sublime (my favorite) or Visual Studio Code. That might not seem like a big deal now, but the more you work with extensions and python, the more you’ll want robust text editing tools at your finger tips.

Externalizing files also reduces bloat in your toe file. If you’ve ever locked a texture in your toe file you know all to well that it your slim file size can quickly balloon. External files also makes it easier to save and try multiple configurations. We’re going to work on a building a calibration UI, we might want to be able to save a calibration configuration and then try another calibration. The same goes for configuration files. Rather than a configuration that’s locked into your toe file, an external file can make it easy to load lots of different configurations or other settings.

It might well seem like I’m belaboring this point, and I’m doing that on purpose. Working with external files is more work, takes more organization, takes better planning, and requires a more meticulous approach – but if you want to grow as a developer and programmer, you’ll wrestle with this challenge sooner or later. I’d encourage you to do that sooner rather than later.

git

What is git? Direct from the git website :

Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.

Git is easy to learn and has a tiny footprint with lightning fast performance. It outclasses SCM tools like Subversion, CVS, Perforce, and ClearCase with features like cheap local branching, convenient staging areas, and multiple workflows.

But what does that mean?! Unlike working with art where a tool like Dropbox would be helpful, when we’re developing software it’s often more helpful to be have some specific means of specifying when a file needs to be saved (probably with the same name), along with a message about what our changes have done. Let’s say we’re working on our calibration UI, we’ve made a change that now allows us to save out our calibration configuration. That’s great, but it’s come at the cost of changing a piece of how our UI works. We know for sure that the old way works 100% of the time, and we’re pretty sure that our new way works at least 80% of the time. Git allows us to check in the new version of our software, commit it to our working directory structure, and make a note of what we did.

We’re smart programmers, so we’ve also started to externalize our files. This means that we’ve separated out parts of our network responsible for different tasks. With git we’re now able to check in only the single tox that’s changed while we’ve been working. Better yet, we can even work with another person. Developer 1 might be working on one part of our project, while Developer 2 is working on another. Both developers are saving their respective tox files, and git allows us to track that progress and merge work seamlessly. If we do end up editing the same files, we end up with a merge conflict… which means what Matt? A merge conflict means just that, two files are competing for the same place in our directory, and we need to review them in order to decide which file to keep.

Git also allows us to work in multiple branches on our project.

Huh?

Let’s imagine that we find a bug, we might want to create a branch in our code to deal with resolving this bug.

Why?

Well, let us imagine a situation familiar to us all. We find a bug, squash it mightily. Only to discover that our fix has created another problem… maybe a much bigger problem. The little bug that we killed we could have worked with, but now we have a show stopper bug running a muck, that we don’t know how to stop, and the show starts in 45 minutes. Trouble shooting in another branch allows you to make fixes and then integrate them back into your project when you’re confident that they don’t create other problems.

Best of all, git creates a history that let’s us step back through each one of our commits. At any point we can return to a past state of our project. Taking advantage of modular design and externalized files makes this even more powerful because it means that with a little work we can resurrect ideas that might otherwise have been lost or discarded.

That’s a big commercial for git so far, but no cautionary tales – an cautionary tales there are plenty of. While git is a phenomenal tool, it can be a bit beastly to wrangle when  you’re first starting – know that you’ll get frustrated, know that you’ll curse it, know that you’ll want to give up on using it, then count to 10 and give it another go. Like all things you’re unfamiliar with, take your time to get used to it as a tool set. You might choose to start by using a GUI tool, but at some point you should learn some of the commands to run directly from the command line. You’ll also want to avoid checking in any of your assets. These days I divide up my projects and separate my assets from my code. I have a few exceptions for this practice, but I try to keep them few and far between – only really allowing for template files, or grids. Essentially, I try to make sure that it’s only files that are going to change in frequently.

If you’re going to use git, you’ll probably also use something like github or bitbucket. These are great services and host your code online so you can get to it from anywhere. These services also come with some great tools for making action items, bug tracking, and maintaining documentation for your project. Take advantage of these tools.

learn more about git at https://git-scm.com/
start using git with github or bitbucket

See more comics from XKCD at https://xkcd.com/

Extensions Everywhere

I’ve talked plenty of about extensions, how to use them, and what they’re good for. I’ve had some spirited discussions about when to use Extensions vs. Modules, and there’s a healthy conversation to be had there for those who want to really get into the weeds of it all. The place I’ve finally landed is this – I use extensions anytime I want to extend the capabilities of a given component. Case to case the degree of extension varies – sometimes I take fuller advantage of using classes than others, and that’s okay. To me, it’s okay if I don’t always take complete advantage of the difference between Extensions and Modules. Sticking with extensions means choosing an approach that works for 99% of the use cases where I need more flexibility in my programming. For mean that means a little bit of stability from the Touch paradigm where there are almost always at least a handful of different ways to solve the same problem. You might like Modules better, and that’s okay. In this case study, however, we’ll see the use of Extensions.

We’ll also see a move away from fragmenting our code across our network. It’s often tempting to use a button deep down in a UI somewhere to perform a logical operation. The only catch is that now that script is buried deep down in your project somewhere, and should it ever give you problems, good luck finding it. For the most part, on large projects I aim to keep the lion share of my operations focused in an extension. This takes a little more time to write, but it means that things are more organized, easier to diff between check ins, that I can change my code in a single place, and that I’m writing functions that are callable from other parts of the network. In my experience so far, this little amount of extra work makes for a larger savings across the whole project.

More about Extensions
Python in TouchDesigner | Extensions
Understanding Extensions

documenting your code – what are docstrings?

I’m a broken record. I know, but really – leave yourself notes, voluminous ones. Better yet, when using extensions make sure to add some docstrings.

“What are docstrings?” you ask.

I’m so glad you did! Docstrings are a feature in several programming languages that allow you to embed  comments or information into your code that can be inspected at run time. If you’re still scratching your head that’s okay. Let’s look at an example, this one is from the wikipedia page about docstrings:

"""
Assuming this is file mymodule.py, then this string, being the
first statement in the file, will become the "mymodule" module's
docstring when the file is imported.
"""

class MyClass(object):
    """The class's docstring"""

    def my_method(self):
        """The method's docstring"""

def my_function():
    """The function's docstring"""

“Great. But why are these useful?”

There useful in lots of ways but for me they have some special importance. For starters, they help ensure that I’m documenting my code as I go. The more tips you leave yourself along the way, the happier you’ll be in the long run. It does make your code longer, and it does take more time. But, if you’re really invested in building something reusable that you can come back to and refine over time, these are solid investments to make that process smoother in the future.

You can get to these notes from anywhere. This internal documentation can be called from anywhere in the network, so if you’ve forgotten how many arguments your method takes, or what it is supposed to return you can get some quick answers without having to track down the extension. When you start to write lots of complex methods this can become a real help. It’s probably not something you need when you’re first working on the project, but if you’re collaborating with someone else or coming back to your project over time it’ll be well worth the time and effort.

Finally worth considering is that docstrings are a part of the larger Python style guide. Like it or not you’re an engineer, and at this point you’re turning into a budding Python programmer. Learning about the best practices of other programmers outside of the TouchDesigner silo helps broaden your perspective and exposes you to how other people work. For better or worse I spent a lot of time in the liberal arts, and one of the core tenants of the ideology that underpins the arts is that exposure to other ideas and perspectives is important in its own right. I’ve carried this with me through life, and I think even in the cases of programming languages it’s worth considering. The conventions and practices of any community teaches you about how they think of the world – how it’s organized, how it aught to work, how that group values the world, or what they don’t value. The Python community is one that we participate in, even if only mostly from our gray network of operators.

learn more about docstrings
see google’s python style guide for docstrings

Mapping out our Project

You know the saying – measure twice, cut once.

Before digging in to a new project make sure you ask a lot of questions, map out as many details as possible, and make a plan.

Okay, so what about our project?

For starters

  • We know that we’ll have five projectors and one monitor that acts as a UI.
  • We know the resolution of all of our displays.
  • We know that we’ll externalize lots of files in our network.
  • We know that we’re going to use git as our version control system.
  • We know that we are going to work with other people.
  • We know that we need to document our work.
  • We know that we’ll need a way to control warping for the five different displays
  • We know that we’ll need a few other controls – both for the mapping, and also to make space for the future UI elements to control playback.
  • We know we need to previs the layout.
  • We know that we’re looking to build out a complete application with all of the features that you might expect from that kind of build.

Whew! Okay, so where do we start? Before we start throwing down ops let’s think through a plan.

We’ll need a container that holds our UI, we’ll also need a container for each of our displays. We know that it’s best to just use a single perform window that spans multiple monitors, so we should make sure we plan for that when we’re developing our project.

We also need to think about how we’re going to set up rendering our scene so we can previs it without turning on all the projectors. That will mean a multi camera set up and some live rendering.

We should also think about how we might ingest video to display for calibration and test playback. On top of that we should also build out a test module to help the creative programmer understand the correct formatting for how to work in the framework we’ve created.

We should also plan to make some space in our build to house assets that are needed across our network, as well as a place to keep our calibration data. We’ll take advantage of the stoner, so we better make some time to pull that apart and better understand how it works.

We’ll use a few set of extensions, so we should also make sure that we know how that works before we dig in too deep.

Finally, we should make sure we know how git works, since we’re going to use that along the way.

We’re bound to run into some other things we need to suss out as we go, but this should give us a solid starting point in terms of understanding the project from a distance.

Next we’ll take a closer look at the stoner to make sure we understand this component we’re going to use, then we’ll dig in and start building.

Exploring Examples from the Forum| TouchDesigner

capture

https://github.com/raganmd/td_fb_forum_examples

New TouchDesigner tool for those of you looking to meander through some examples.

Pull this whole repo and find example_explorer.toe in:{your_local_directory}\td_fb_forum_examples\example_explorer

All the examples I’ve collected appear as a list on the far left, read me docs display in the middle viewer, and the example network shows up on the right.

For right now, use the “h” key to home the network when you load a new tox. Tracking down the right way to have that happen automatically – coming soon.

As a bonus this has a functioning list comp that you’re welcome to pillage.

Only a single example is loaded at a time to try and keep things optimized.

If you’re teaching a course and could benefit from re-purposing this network design for assignments or examples please feel free.

Python in TouchDesigner | Modules | TouchDesigner

There are a number of ways that we might use modules on demand in TouchDesigner. Before we get too far along, however, we might first ask “what is a module on demand?”

According to the TouchDesigner wiki:

The MOD class provides access to Module On Demand object, 
which allows DATs to be dynamically imported as modules. 
It can be accessed with the mod object, found in the automatically 
imported td module. 

Alternatively, one can use the regular python statement: import. 
Use of the import statement is limited to modules in the search path, 
where as the mod format allows complete statements in one line, 
which is more useful for entering expressions. Also note that DAT modules 
cannot be organized into packages as regular file system based 
python modules can be.

What does this mean? It’s hard to sum up in just a single sentence, but the big thing to take away is that we can essentially use any text DAT to hold whole functions for us that we can then call whenever we want.

Let’s take a closer look at this process. We’ll start with some simple ideas, then work our way up to something a little more complicated.

First we turn things way down, and just think about storing variables. To be clear, we probably wouldn’t use this in a project, but it can be helpful for us when we’re trying to understand what exactly is going on here.

Let’s create a new text DAT and call it “text_variables”, inside let’s put the following text:

width       = 1280
height      = 720

budget      = 'small'

Using the mod class we can access these variables in other operators! To do this we’ll use the following syntax:

mod( 'text_variables' ).width
mod( 'text_variables' ).height
mod( 'text_variables' ).budget

Try adding a constant CHOP, and a text TOP to your network and using the expressions above to retrieve these values.

Next try printing these values:

print( mod( 'text_variables' ).width )
print( mod( 'text_variables' ).height )
print( mod( 'text_variables' ).budget )

So, it looks like we can access the contents of a module as a means of storing variables. That’s hip. Let’s take a moment and circle back to one of the other use cases that we’ve already seen for a module. More than just a single value, we can also put a whole dictionary in a module and then call it on demand. We’ve already done this in some of our previous examples, but we can take a quick look at that process again to make sure we understand.

Let’s create a new text DAT called “text_dictionary_as_module”, inside of this text DAT let’s define the following dictionary:

fruit = {
    "apple" : 10,
    "orange"    : 5,
    "kiwi"  : 16
}

Let’s first print the whole dictionary object:

print( mod( 'text_dictionary_as_module' ).fruit )

Alternatively, we can also access individual keys in the dictionary:

mod( 'text_dictionary_as_module' ).fruit[ 'apple' ]
mod( 'text_dictionary_as_module' ).fruit[ 'orange' ]
mod( 'text_dictionary_as_module' ).fruit[ 'kiwi' ]

What can you do with this?! Well, you might store your config file in a text DAT that you can call from a module on demand. You might use this to store configuration variables for your UI – colors, fonts, etc. ; you might decide to use this to configure some portion of a network, or to hold on to data that you want to recall later; or really any number of things.

Before we get too excited about storing variables in modules on demand, let’s look at an even more powerful feature that will help us better understand where they really start to shine.

Up next we’re going to look at writing a simple function that we can use as a module on demand. In addition to writing some simple little functions, we’re also going to embrace docstrings – a feature of the python language that makes documenting your work easier. Docstings allow us to leave behind some notes for our future selves, or other programmers. One of the single most powerful changes you can make to how you work is to document your code. It’s a difficult practice to establish, and can be frustrating to maintain – but it is hands down one of the most important changes you can make in how you work.

Alright, I’ll get off my documentation soapbox for now. Let’s write a few methods and see how this works in TouchDesigner.

We can start by creating a new text DAT called “text_simple_reutrn”, inside of this DAT we’ll write out our new functions:

Great! But what can we do with these? We can start by using some eval DATs or print statements to see what we’ve got. I’m going to use eval DATs. Let’s add several to our network and try out some calls to our new module on demand. First let’s look at the generic syntax:

mod( name_of_text_dat ).name_of_method

In practice that will look like:

mod( 'text_simple_reutrn' ).multi_by_two( 5 )
mod( 'text_simple_reutrn' ).multi_by_two( 2.5524 )
mod( 'text_simple_reutrn' ).logic_test( 5 )
mod( 'text_simple_reutrn' ).logic_test( 6 )
mod( 'text_simple_reutrn' ).logic_test_two( "TouchDesigner" )

Now we can see that we wrote several small functions that we can then call from anywhere, as long as we know the path to the text DAT we’re using as a module on demand! Here’s where we start to really unlock the potential of modules on demand. As we begin to get a better handle on the kind of function we might write / need for a project we can begin to better understand how to take full advantage of this feature in TouchDesiger.

Doc Strings

Since we took the time to write out all of those doc strings, let’s look at how we might be able to print them out! Part of what’s great about doc strings is that there’s a standard way to retrieve them, and therefore to print them. This means that you can quickly get a some information about your function printed right in the text port. Let’s take a closer look by printing out the doc stings for all of our functions:

That worked pretty well! But looking back at this it seems like we repeated a lot of work. We just learned about for loops, so let’s look at how we could do the same thing with a loop instead:

A Practical Example

This is all fun and games, but what can we do with this? There are any number of functions you might write for a project, but part of what’s exciting here is the ability to write something re-usable in Python. What might that look like? Well, let’s look at an example of a logger. There are a number of events we might want to log in TouchDesigner when we have a complex project.

In our case we’ll write out a method that allows a verbose or compact message, a way to print it to the text port or not, and a way to append a file or not. Alright, here goes:

So now that we’ve written out the method, what would call for this look like?

operator = me

message ='''
Just a friendly message from your TouchDesigner Network.
Anything could go here, an error message an init message.

You dream it up, and it'll print
'''

# print and append log file with a verbose log message
mod( 'text_module1' ).Log_message( operator, message, verbose = True )

# print and append log file with a compact log message
# mod( 'text_module1' ).Log_message( operator, message )


# append log file with verbose log message
# mod( 'text_module1' ).Log_message( operator, message, verbose = True, text_port_print = False )


# print a compact log message
# mod( 'text_module1' ).Log_message( operator, message, append_log = False )

Take a moment to look at the example network and then un-comment a line at a time in the text DAT with the script above. Take note of how things are printed in the text port, or how they’re appended to a file. This is our first generalized function that has some far reaching implications for our work in touch. Here we’ve started with a simple way to log system events, both to a file and to the text port. This is also a very re-usable piece of code. There’s nothing here that’s highly specific to this project, and with a little more thought we could turn this into a module that could be dropped into any project.

Local Modules

We’ve learned a lot so far about modules on demand, but the one glaring shortcoming here is that we need the path to the text DAT in question. That might not be so bad in some cases, but in complex networks writing a relative path might be complicated, and using an absolute path might be limiting. What can we do to solve this problem. We’re in luck, as there’s one feature of modules we haven’t looked at just yet. We can simplify the calling / locating of modules with a little extra organization.

First we need to add a base and rename it to “local”, inside of this base add another base and rename it to “modules”. Perfect. I’m going to reuse one of our existing code examples so we can see a small change in syntax here. I’ve also changed the name of the text DAT inside of local>modules to “simple_return”.

mod.simple_return.multi_by_two( 5 )
mod.simple_return.multi_by_two( 2.5524 )
mod.simple_return.logic_test( 5 )
mod.simple_return.logic_test( 6 )
mod.simple_return.logic_test_two( "TouchDesigner" )
mod.simple_return.logic_test_two( 10 )

Looking at the above, we can see that we were able to remove the parentheses after “mod”. But what else changed? Why is this any better? The benefit to placing this set of functions in local>modules is that as long as you’re inside of this component, you no longer need to use a path to locate the module you’re looking for.

Alright, now it’s time for you to take these ideas out for a test drive and see what you can learn.

Python in TouchDesigner | Data Structures – Dictionaries | TouchDesigner

Part 1 Core Concepts

  • Dictionaries – a structure and a concept
  • Looking at Dictionaries and Lists side by side
  • What are key value pairs
  • Retrieving values from dictionaries
  • Retrieving .keys() and .values()
  • Adding items to dictionaries
  • Nested data structures
  • A better text formatting approach with .format() (a big thank you to Willy Nolan for setting me on the right path with text formatting in Python 3)


Part 2 Core Concepts

  • Dictionaries – a structure and a concept
  • A practical look at dictionaries in TouchDesigner
  • Nested data structures – dictionaries in dictionaries
  • Using Dictionaries as a preset structure
  • Using Python to set parameters
  • Using Python variables in scripts to generalize our code


This isn’t the first time I’ve been on a tear about using Dictionaries in TouchDesigner – THP 494 & 598, Presets. That said, sometimes it’s easier to understand a concept if we back down a little bit and start from the beginning. With that in mind, let’s turn the speed down to 0.1 before we turn it up to 12 again.

Dictionaries are another type of data structure that we can use in Python. They’re similar to lists in that we can store information in them, and retrieve them easily. Dictionaries, however, are distinctly different from lists. Where lists are index based – which is to say that they have a specific order – dictionaries are key based.

What does that mean, and why do we care?! We think of dictionaries as being a pair of things a key, and a value. We might think of this as a name and its corresponding piece of information. Let’s look at something simple to get started. To get started let’s go back to our grocery example when we were talking about lists. In making a list for our trip to the grocery store we listed all of the items we needed from the store. We didn’t however, make any notes about quantity. Let’s quickly make that list again:

grocery_list = [ 'eggs' , 'milk' , 'bread' , 'butter' , 'coffee' ]

This is great, and it tells us lots of information, but maybe not all of the information we need. If I’m going to the store myself, this is a fine list. If I’m asking someone else to pick up these things for me, well then I need at least one other piece of information – quantity. If we’re using lists, we might do something clever, like make a list of lists with two items – the grocery item, and the desired quantity. That might look something like this:

grocery_list = [ 
    ['eggs' , '1 dozen' ] , 
    ['milk' , '1 pint' ] , 
    ['bread' , '2 loaves' ] , 
    ['butter' , '1 lb' ] , 
    ['coffee', '2 lbs' ]
]

This works fine, and might be a great way to hold onto this information. We can, however, use a dictionary to do this same thing. In this case we’re going to think of our grocery items as a keys, and quantities as values. Let’s look at what means:

grocery_list = {
    'eggs' : '1 dozen' , 
    'milk' : '1 pint' , 
    'bread' : '2 loaves' , 
    'butter' : '1 lb' , 
    'coffee': '2 lbs'
}

It’s important to note that I’ve used some indenting to make this easier to read, but another perfectly valid way to write this dictionary would be:

grocery_list = { 'eggs' : '1 dozen' , 'milk' : '1 pint' , 'bread' : '2 loaves', 'butter' : '1 lb' , 'coffee': '2 lbs' }

I just happen to think that anytime you can make something easier to read by a human, the better.

Okay, let’s talk about syntax here for a second. So the first thing we did was declare our dictionary as a variable. Next we used curly brackets to open our dictionary ( {} – these are curly brackets ). Next we wrote out our dictionary as key and value pairs separated by a colon – keys on the left, values on the right. Now in this example all of our values were strings, but they could just as easily have been integers, floats, booleans, lists, or even other dictionaries.

This is all well and good, but how do we get things out of our dictionary? We know how to retrieve things from a list, but a dictionary is a little different. When retrieving something from a dictionary we typically use a key. Let’s consider our first example again for a second. Let’s say we want to print out the quantity of eggs that we’re supposed to get from the store. We can do that like this:

print( grocery_list[ 'eggs' ] )

We can also retrieve the contests of dictionary with .keys() and .values():

print( grocery_list.keys() )
print( grocery_list.values() )

In both of these cases we get a list of keys or values.

It’s also important to know how to add items to our dictionary. There are a few ways to go about this, but let’s just look at one for now. We should start by creating an empty dictionary:

my_dictionary = {}

Now that we have an empty dictionary, we can add items to it. We do this by starting with the dictionary name, then placing the key in square brackets ([] these things), followed by an equal sign, and then what we want to be placed into the dictionary as the value. Let’s look at an example:

my_dictionary[ 'new_item1' ] = "cookies"

Okay, now that we’ve added one key value pair, let’s print out the keys and values in our list (to practice), and add a few more items:

my_dictionary = {}

my_dictionary[ 'new_item1' ] = "cookies"

print( my_dictionary.keys() )
print( my_dictionary.values() )

my_dictionary[ 'new_item2' ] = "cell_phones"

print( my_dictionary.keys() )
print( my_dictionary.values() )

my_dictionary[ 'new_item3' ] = 55

print( my_dictionary.keys() )
print( my_dictionary.values() )

my_dictionary[ 'new_item4' ] = [ 1 , 2 , 3 ]

print( my_dictionary.keys() )
print( my_dictionary.values() )

Wait… what did we just do there with item4?! Most of that should look pretty straightforward, and hopefully that makes sense for the most part. It is not, however, the most exciting part of using dictionaries. Dictionaries become the most exciting when we start to see how we can nest other lists or dictionaries inside of them.

Let’s look at a dictionary of mixed contents:

my_dictionary = { 
    "apple" : "these are delicious" , 
    "orange" : 12 , 
    "kiwi" : 55.5 , 
    "lots_of_things" : [
        "paper" , 
        "pens" ,
        44 , 
        10.4
    ] 
}

So we know how to get to the values associated with “apple” , “orange” , and “kiwi” , but how do we get to the contents of that list? Well, we can write something like this:

print( my_dictionary[ 'lots_of_things' ][ 0 ] )
print( my_dictionary[ 'lots_of_things' ][ 1 ] )
print( my_dictionary[ 'lots_of_things' ][ 2 ] )
print( my_dictionary[ 'lots_of_things' ][ 3 ] )

Here we see the same syntax that we use when retrieving list items.

That’s wonderful! So what about when we store dictionaries inside of dictionaries? Let’s look at a simple example. We can start by creating a dictionary with fruit’s as our keys. Each fruit will have a corresponding dictionary of quantity, origin, and if the fruit is organic. Okay, what would that look like:

my_dictionary_of_dictionaries = { 
    "apple" : {
        "quantity" : 10 ,
        "origin" : "Vermont" ,
        "organic" : True 
    } , 
    "orange" : {
        "quantity" : 20 ,
        "origin" : "California" ,
        "organic" : False
    } , 
    "kiwi" : {
        "quantity" : 26 ,
        "origin" : "Mexico" ,
        "organic" : False
    } , 
    "grapes" : {
        "quantity" : 50 ,
        "origin" : "Peru" ,
        "organic" : True
   }
}

That’s pretty snazzy and all, but how do we pull things out of this data structure? We can follow the example we learned with lists, but instead of using index values, we can instead use keys. Let’s look at just apple to get started:

print( "Let's just look at apple" )
print( "quanitity -" , my_dictionary_of_dictionaries[ 'apple' ][ 'quantity' ] )
print( "origin -" , my_dictionary_of_dictionaries[ 'apple' ][ 'origin' ] )
print( "organic -" , my_dictionary_of_dictionaries[ 'apple' ][ 'organic' ] )

Here we can see that we start with our dictionary, with a key in square brackets, followed by another key in square brackets. Practice retrieving other keys – what about grapes, or oranges? Also practice by adding other keys inside of the fruit dictionaries. Don’t forget to pay careful attention to where you’ve placed your commas and, remember that keys are strings so they need quotation marks.

Once you’ve done that, let’s consider how we might use something like a dictionary here in TouchDesigner. We’re going to look something a little complex, but still relatively simple to help us get our bearings. Dictionaries can be a great help to us when we want to do things like creating save states. Let’s first think about what it would mean to set the properties of a text TOP with the contents of a dictionary.

Let’s start by making our dictionary. I’m going to use the same names for our dictionary keys that we find in our parameter names – just to make sure we know exactly where a value is going.

top_dictionary = { 
    "text" : 'monkey' , 
    "fontsizex" : 15 ,
    "alignx" : 1 ,
    "aligny" : 1 ,
    "fontcolorr" : 1.0 ,
    "fontcolorg" : 0.0 ,
    "fontcolorb" : 0.0 ,
    "fontalpha" : 1.0 ,
    "bgcolorr" : 0.0 ,
    "bgcolorg" : 0.0 ,
    "bgcolorb" : 0.0 ,
    "bgalpha" : 1.0
}

Now let’s flesh out our script to change the parameters of our TOP:

target_text = op( 'text1' )

target_text.par.text = top_dictionary[ 'text' ]

target_text.par.fontsizex = top_dictionary[ 'fontsizex' ]
target_text.par.alignx = top_dictionary[ 'alignx' ]
target_text.par.aligny = top_dictionary[ 'aligny' ]
target_text.par.fontcolorr = top_dictionary[ 'fontcolorr' ]
target_text.par.fontcolorg = top_dictionary[ 'fontcolorg' ]
target_text.par.fontcolorb = top_dictionary[ 'fontcolorb' ]
target_text.par.fontalpha = top_dictionary[ 'fontalpha' ]
target_text.par.bgcolorr = top_dictionary[ 'bgcolorr' ]
target_text.par.bgcolorg = top_dictionary[ 'bgcolorg' ]
target_text.par.bgcolorb = top_dictionary[ 'bgcolorb' ]
target_text.par.bgalpha = top_dictionary[ 'bgalpha' ]

That’s pretty great – but goodness that’s a lot of work just to change some settings. How might we think about using this idea to create a preset system? We’re not that far off form this idea at this point, so let’s dig in a little deeper. To really make this work, we need to revisit our dictionary. Specifically, we need to encapsulate our presets inside another layer. We need to make them their own dictionary as a set of values for another key. For example, we might want a named structure like “preset1” , “preset2” etc. to be how we retrieve settings. Let’s change our dictionary to make that happen:

top_dictionary = { 
    "preset1" : {
        "text" : 'monkey' , 
        "fontsizex" : 15 ,
        "alignx" : 1 ,
        "aligny" : 1 ,
        "fontcolorr" : 1.0 ,
        "fontcolorg" : 0.0 ,
        "fontcolorb" : 0.0 ,
        "fontalpha" : 1.0 ,
        "bgcolorr" : 0.0 ,
        "bgcolorg" : 0.0 ,
        "bgcolorb" : 0.0 ,
        "bgalpha" : 1.0
    } ,
    "preset2" : {
        "text" : 'pig' , 
        "fontsizex" : 80 ,
        "alignx" : 1 ,
        "aligny" : 0 ,
        "fontcolorr" : 0.0 ,
        "fontcolorg" : 0.0 ,
        "fontcolorb" : 1.0 ,
        "fontalpha" : 1.0 ,
        "bgcolorr" : 1.0 ,
        "bgcolorg" : 1.0 ,
        "bgcolorb" : 1.0 ,
        "bgalpha" : 1.0
    }
}

Not bad. Now, how can apply these presets to our top? To do this we’re going to do one tricky thing. We’re going to write our scripts so that a python variable can stand in our first key. This will mean that we only need to change a single variable before re-running our script. That would look like this:

target_text = op( 'text1' )
dictionary_preset = 'preset2'

target_text.par.text = top_dictionary[ dictionary_preset ][ 'text' ]
target_text.par.fontsizex = top_dictionary[ dictionary_preset ][ 'fontsizex' ]
target_text.par.alignx = top_dictionary[ dictionary_preset ][ 'alignx' ]
target_text.par.aligny = top_dictionary[ dictionary_preset ][ 'aligny' ]
target_text.par.fontcolorr = top_dictionary[ dictionary_preset ][ 'fontcolorr' ]
target_text.par.fontcolorg = top_dictionary[ dictionary_preset ][ 'fontcolorg' ]
target_text.par.fontcolorb = top_dictionary[ dictionary_preset ][ 'fontcolorb' ]
target_text.par.fontalpha = top_dictionary[ dictionary_preset ][ 'fontalpha' ]
target_text.par.bgcolorr = top_dictionary[ dictionary_preset ][ 'bgcolorr' ]
target_text.par.bgcolorg = top_dictionary[ dictionary_preset ][ 'bgcolorg' ]
target_text.par.bgcolorb = top_dictionary[ dictionary_preset ][ 'bgcolorb' ]
target_text.par.bgalpha = top_dictionary[ dictionary_preset ][ 'bgalpha' ]

Alright. Looking closely at the above, we can see that we need only change the variable “dictionary_preset” in order to fetch a whole different set of values. Not bad, right?

Take some time to experiment with these ideas. As we head forward we’re going to start to look at how we can use executes and for loops to see how we can really start to make headway in using Python. We’ve laid a lot of ground work so we can really plow ahead.

Learn more about Python Data Structures

Download the sample files from github

Understanding Referencing Part II | TouchDesigner

14497860106_434af77e0f_mI 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.

switch top 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.

textport

When you open your textport you should see a floating window that looks like this:

textport windowGreat! With your Movie In TOP, Text DAT, and Textport you should be looking at something like this:

movie in and text

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:

print(“hello world”)

helloworld

We can also complete this same operation using our text DAT. In the text DAT write:

print(“hello world”)

hello world DAT

Now right click on the DAT, and select “Run Script” from the drop down menu. You should see the text appear in your textport:

hello world gifCongratulations, 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.

members

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:

op(‘moviein1’).width

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:

print(op(‘moviein1’).width)

Now if you run the script you should see:

print width

Let’s try one more. Let’s add one more line of code:

print(op(‘moviein1’).height)

Let’s run the script one more time and you should have something that looks like this:

width and height

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,

text tops

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:

connections

Using what we just learned, write the following script into your text DAT:

print(op(‘switch1’).inputs)

When you run this script you should see something like this:

print inputs

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:

print(len(op(‘switch1’).inputs))

When you run the script you should see this:

print len

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:

button count

Let’s also make sure that the button is set to momentary:

button 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:

count CHOP

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:

count click

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

Understanding Referencing | TouchDesigner

referencingReferencing 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.

all reference typesIn 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.

viewer activeLet’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):

exportAs 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:

export CHOPLooking 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:

source_operator_name:source_channel_name

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:

current valueAll of these are ways that we can connect two operators together, and many of them yield the same results, so what gives:

  • Export CHOP – we’ve already seen this method, and we know that one of its limitations is that it creates a fixed relationship between two operators. This is excellent for creating something more finished for locked in nature.
  • Text – Text exports the pathway to a particular channel.
  • Current CHOP Value – this exports the value of the operator in question at the precise moment that you drag and drop. Rather than a continually updating value this is just a single float or integer.
  • Relative CHOP Reference – the relative reference exports a python expression that points to the operator being referenced. A relative makes for easy cutting and pasting so long as the network hierarchy relationships remain constant between operators.
  • CHOP Reference (sometimes called Absolute Reference) – the absolute reference also creates a python expression pointing to an operator. The difference here is that it includes the precise pathway to the operator in question making cutting and pasting a bit more frustrating.

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.

Relative Referencing

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.

relative referenceTaking a closer look at our expression we can see that it reads:

op(“noise1”)[“chan1”]

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:

fruit constantAlright, 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:

op(‘fruits’)[‘apple’]

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:

fruits topIf 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:

op(‘fruits’)[‘pear’]
op(‘fruits’)[‘lemon’]

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”.

constant1So how does ../ work then? Imagine that you’d like the alpha of the constant in our geo to be connected to the noise in our parent network. Here we can write a reference that looks like this:

op(‘../noise1′)[‘chan1’]

Here’s what that would look like:

dot dot slash

Absolute References

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:

op(“references/noise1”)[“chan1”]

absoluteAbsolute 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

 

 

 

Geometric Landscapes | TouchDesigner

rolling landscapeWorking on a new piece to premiere in Mexico I spent a lot of time experimenting with creating landscapes and backgrounds. Searching for a way into this exploration I wanted to play with the idea of instancing objects in 3D space, and the illusion of moving and shifting planes in space. This is already a popular visual style, and I was wanted to try my hand at exploring what it might look like to make something like this in TouchDesigner.

I’ve talked about instancing before, and so this challenge seemed like something that would be both fun, and interesting to play with. I also wanted something that mixed material methods – shaded, flat, and wire frame in appearance. Let’s take a look at how we can making something interesting happen using these ideas as a starting point.

Rendering is going to make or break us when thinking about how to set up this project, with that in mind it’s important to remember that a typcially rendering set-up needs something to be rendered (some geometry), a perspective from which to draw the object(s) (a camera), and a light source (a light, we don’t always need a light but as a rule of thumb it’s good to think that we need one). Our Geometry, Light, and Camera are all components, while our render operator is a Texture Operator (TOP). As a point of reference, here’s what a generic rendering set-up looks like:

classic render setup

We can tell our Render TOP to look at multiple Geometry Components, in the same network, or we can nest our active surfaces inside of a single GEO. Much of this depends on what you’re looking to create. The most important thing to consider is that surfaces operators (SOPs) are computed on the CPU unless placed inside of Geometry COMP – placed inside of a Geo they’re computed on the GPU instead. This makes a huge difference in your performance, and as a best practice it’s good to place any rendered geometry inside of a Geo.

Now let’s take a look at what our rendering set-up is going to look like for making our geometric landscape:

rolling landscape render set-up

Here we can see that we have a similar set-up on the left – a light, a geo, a camera, and a Render TOP. On the right I’ve got the geometry viewer open so we can see a little more about the relationship in the scene of the camera, light, and geometry. We can see that the camera is set above our geometry looking down, we can also see that we have a cone light set-up with a wide angle and a wide delta.

Now that we have a general sense of what we’re making let’s dig-in and make something interesting.

Lets start with an empty network. Lets start by adding a Geo to our network.

geo

To get started we’ll need to dive inside of geo to start making some changes. You can do this by double clicking on the Geo, using the quick key “i” (shortcut for inside), or by scroll wheel zooming into your geo. Inside our Geo we’ll see a torus that has it’s render and display flag set (the small blue and purple circles on the surface operator).

Inside of our geo let’s start by frist deleting the Torus SOP. Next let’s add a Grid SOP. Our grid is going to act the key generative element for us inside of this network – it’s going to give our surface its wire texture, the shading on the surface, and the location of where our spheres get placed. Our Grid is the central piece of what we’re making, and we’ll how in just a bit. Once we’ve added a grid to our network, we need to make a few changes to some its properties. First we want to make sure that it’s set to be a Polygon for Primitive type; we want to make sure that our orientation is set to ZX Plane; finally we want to change the size to 20 x 20.

grid setup

Next we’ll connect our Gird SOP to a Noise SOP. We’re going to use the Noise SOP to drive some of the shifting locations of the points in our grid. Before we move on, let’s make one quick change, On the Transform page in the Noise SOP’s parameter’s we can see that the translate z parameter is set to change with the second count of our project – me.time.seconds. This is excellent, and it keeps our noise animated over time, but it also means that we’re only working with 600 samples (in a default TouchDesigner network) because me.time.seconds is locked to our timeline. If, instead, we want noise that doesn’t have a hiccup every 10 seconds, we can instead use the call me.time.absSeconds. This uses the absolute number of seconds that TouchDesigner has been running to drive the transformations in the noise SOP. It’s a small change, but makes for a nicer look (at least in my opinion).

noise SOP

Next we’ll add a Material SOP to the our network. Our material SOP is going to allow us to assign a material to our grid. We’ll do this by also adding a Wireframe Material to our network. Before we assign our wireframe to our material we should see something like this:

before assignment

To assign the wireframe to the material, we’re just going to drag and drop the MAT onto the SOP.

assign MAT

Finally, we’re going to end this string by adding a Null SOP, making sure to turn on the render and display flags.

wire null

At this point we’ve made the Wireframe outlined elements of our grid. We’re now going to use the same data stream that we’ve already programmed to help us create a another layer of texture, and to create the locations for our spheres. Let’s start by adding our spheres to the network. To do this we’re going to do some instancing. When we’re instancing we need some location information for where to generate the copies of our source geometry. To get this information we’re going to use a SOP to CHOP to convert our SOP information into CHOP data.

SOPtoNow before we move on we need to change gears for just a moment. What we’re going to do next is to add another Geo inside of our current Geo – in Russian Nesting Doll Fashion. Why? Well, we’re going to do this in order to take advantage of the Geo’s ability to instance. Why not use the Copy SOP? I love me some Copy SOP action, but in this case the use of instancing is more efficient for this particular activity.

So, let’s add another Geo to our network:

new geo

Next we’re going to replace the torus inside of this Geo with a sphere. We’re also going to add a material inside of the geo. Easy, right? I’m going to set my sphere to be pretty small ( 0.09, 0.09, 0.09 ), I’m also going to make sure that I connect my sphere to a Null (in case I want to make any other changes), and then turn on the Null’s display and render flags. Finally I’m going to add a constant Material. When we’re all said and done you should have something like this:

inside the sphere

Excellent. Now we we back out of this nested Geo we should see just a single sphere. What?! Well, now we can set the Geo to instance – my favorite part.

small sphere

Let’s start by taking a look at the parameters of our Geo. Specifically, we want to look at the Instance page. Here we first need to turn on Instancing. Next we’re going to tell our Geo to look at the CHOP called sopto1. Finally we’ll set the TX, TY, and TZ parameters to correspond to the channels called tx, ty, and tz. If this seems like crazy talk, that’s okay – check out the picture below and it should make more sense:

instance page

We also want to head to Render Page of the Geo, and set this geo to use the material ./constant1 (this means, use the material inside of this geo called constant1 – ./ is a directory pointer indicating where to look for the thing in question, in this case a constant).

constant

Alright, now we can finally see some of our handy work – you should now see a sphere instanced at each of the vertices of the grid that we’re transforming with noise.

Spheres

Now let’s kick it up a notch. Now we’re going to add another Geo to our network.

last geo

We’re going to treat this Geo slightly differently. Inside let’s add an In SOP and a Phong Material. On our SOP In let’s make sure that the display and render flags are turned on, and for your SOP choose a nice dark color – I’m choosing a deep crimson.

geo3

The In SOP allows us to pass in the geometry that we’ve already made, acting as a kind of short-cut for us. When we go back to our Geo we just need to make sure that we’ve set our Render material to be ./phong1 – like with our constant this is the pathway to and the name of the material we want to use.

geo3mat

Alright, now you should have a network that looks something like this:

complete geo network

Now we’re ready to move out of our Geo and get ready to render our scene. Zooming out of our Geo we should see a network that looks something like this:

work space

In order to render our scene we need to revisit what we talked about at the beginning of the post – we need to add a Camera, a Light, and a Render TOP. Let’s go ahead and add these to our network.

rendersetupGeo

What gives?! This doesn’t look right at all. Well, part of what’s happening is that we don’t have our camera and light positioned correctly to render the scene correctly. To make this easier to understand, let’s change up our work space so we can use the geometry viewer (one of my favorite tools). Let’s start by dividing the workspace into two windows. We can do this by using the split work space icon in the menu bar:

menu bar

I like the vertical split, but you can choose whatever arrangement works for you. When you initially click on this split you’ll see two views of your current network location:

split step1

In order to see the geometry viewer we need to change the pane type selection for one of our windows. Clicking on the small drop down triangle will reveal a menu of network views. Let’s select Geometry Viewer from the list.

pane type

You should now see your network on one side, and the geometry from our Geo comp on the other side.

geo viewer

Now we’re cooking with gas. Alright, let’s make our lives just a little easier and change the scale of our light and camera to make them easier to see. Click on your light COMP, if your parameters window has disappeared you can bring it back by pressing “p” on your keyboard.” In the scale parameter, let’s turn that up to 10, 10, 10.

light scale

Great, now we can see part of the reason that our scene isn’t rendering the way we want it to. Our light is currently set up as a point light that’s positioned at the edge of our geometry. Let’s make some changes to our light’s properties so we get something closer to what we want. Let’s start by changing the location of our light, I’m going to place mine at 0, 10, 0.

lightplacement

Now let’s take a look at the Light page of the parameter’s window. Here I’m going to change my light to a Cone, and alter the cone size, delta, and rolloff. Experiment with different settings here to find something that you like.

light properties

Before you get too much experimenting done, however, you’ll probably notice that the cone of our light isn’t pointing towards the surface of our geometry. We can fix this by heading back to the Xform page of the parameters window, and setting the rotation values to -90, 0, 0.

light ROT

With our light starting to take shape, let’s get our camera in order. Over at our camera, let’s make the same initial change we made to the light and turn the scale up to 10, 10, 10 – this is going to make it much easier for us to find our camera.

cameraScale

With the scale turned up we can see that our camera needs to be translated back, up and rotated downwards so it’s looking at the geometry. After a little bit of adjusting I think I like my camera at:

TX    0
TY    6.2
TZ    18.9
RX    -16.8
RY    0
RZ    0

cameraTrans

Boom! Alright, let’s close our geometry viewer and take a closer look at our Render TOP to see what we’ve made.

finalRender

Nice work. This is a good looking start, and now that you know how it’s made you can start to really have fun – camera placement, light placement, noise amplitude, you name it, go crazy, make something fun or weird, or just silly.

Inspired by Rutt Etra | TouchDesigner

Fall of the House of EscherBack when I was working on The Fall of the House of Escher I became obsessed with live z-displacement in the media. That particular show was wrestling with questions of quantum physics, time, reality, and all manner of perceptual problems and so it made a lot of sense to be love the look and suggested meaning inherent in the displacement of an image in a third dimension. This particular technique is perhaps most well known to us because of the Rutt Etra Video Synthesizer. This video synth was an attempt to begin manipulating video in same manner as sound was being manipulated in the 1970s, and was truly a ground breaking examination of our relationship to video – live video especially. One of the most famous elements of the Rutt Etra Synth was z displacement, the change in the depth of an image based on its luminance.

You can get a better sense of what this kind of effect looks like by playing with the Rutt Etra-izer online. This simple tool lets you play with one slice of what the original video synth did. Additionally, if you’re a mac user you might want to check out what v002 had to share when it comes to plug-ins, as well as some thoughts from Bill Etra. You can find more from v002 here: Rutt Etra v002

So that’s all well and good, but what am I after? Well, in the pursuit of better understanding how to program with TouchDesigner, as well as how to explore some of the interesting ideas from the 1970s, I wanted to know how to replicated this kind of look in a TouchDesigner network. There are plenty of other people who have done this already, and that’s awesome. I, however, happen to subscribe to the kind of art philosophy asks students to copy the work of others – to practice their hands at someone else’s technique, to take what works and leave what doesn’t. Art schools have often required students to copy the work of masters in order to foster a better appreciation and understanding of a particular form, and I think there’s a lot too that in programming. So today, we’ll look at how to make this kind of effect in TouchDesigner and then ask how we might manipulate this idea in ways that differ from how the original method was intended to  work.

Rutt Etra almostTo begin, this idea started when I was looking through the wiki page about Generative Design. Specifically, the sample network talking about image manipulation really got my attention. Buried in this example network is something that’s Rutt Etra flavored, and it’s from this example that I started to pull out some ideas to play with. As we work our way through this example it’ll be easy to get lost, frustrated, or confused. Before that happens to you, take a moment to think about what we’re trying to do. Ultimately, we want to take an image (video later, but for now an image) and add together the RGBA values of an individual pixel and use that number to transform said pixel in a z dimension. In other words, we’re really after creating a faux depth map out of an image. It’s also important to remember that using an image that’s 1920 x 1080 means we’re talking about 2,073,600 pixels. That’s a lot of points, so we’re going to start by creating a grid that simplifies those dimensions – partially for our own sanity, partially for the sake of the processing involved, and partially to remain true the aesthetic of the original idea. Once we replicate the original, then we can start to talk about where we can start to play. That’s enough disclaimers for us to get started, so let’s do some programming.

Let’s start by looking at the whole network:

From this vantage point we can see that we’re going to make a network that uses a little bit of everything – some texture operators (TOPs), some channel operators (CHOPs), and some surface operators (SOPs).

Starting with Texture Operators

First things first, let’s make a new container and dive inside. To our empty container let’s start by adding an In TOP as well as a Movie In TOP. We’re going to start by connecting the Movie In to the second input on the In TOP. Why? The Movie In TOP is going to allow us to pass a video stream into this container. We may, however, want some image to show up while we’re working or when we don’t have a video stream coming in; this is where that second input comes in handy. This gives us a default image to use when we don’t have a stream coming into the container. Here’s what you should have so far:

in

Next, we want to down sample some of this image. This step is actually helping us plan ahead, we’re going to use some expressions to set the parameters of some of our other operators, and this step is going to help us with that. To do this down-sampling, we’re going to use the Resolution TOP. After that we’ll end our TOP string in a Null TOP. All of that should look like this:

Rutt-TOPs

Before we move on, let’s make on change to the resolution TOP in our string. Open up the parameters window for your resolution TOP and on the common page change the Output Resolution parameter to Quarter:

resolution

 

Channel Operators

There are a number of different transformations that we’ll need to do with the data from our image, we’ll start this process by first moving to Channel operators. If we think back to where we started this process with an intent to transform luminance into depth, then we know that one of the operations we need to complete is to add together the RGBA values of our pixels in order to have a single number we can use to manipulate a surface. To get us started we first need to convert our image into channel data that we can manipulate. To do this we’re going to add a TOP to CHOP to our network. This operator is going to allow us to look at our TOP as if it were all Channel data. We’ll see what that looks like in a moment. First, however, let’s make a few changes to our operator. In the Image page for the TOP to make sure that you’re set to “Next Frame” as the download type. On the Crop page you’ll also want to make sure that you’re set to the full image:

Next we need to assign a TOP so we have a texture that we’re converting into Channel data. You can do this by dragging the TOP onto this CHOP, or you can enter in the name of the target TOP on the image page. Your TOP to CHOP, should now look something like this:

top to chop

This viewer on this operator can be taxing on your system, so at this point I’d recommend that you click the small bulls-eye in the upper left hand corner of your CHOP to turn off the viewer. This will save you some system resources as you’re working in your network and keep you from seeing too much lag while you’re editing this network.

The next series of channel operators is going to allow us to make some changes to our data. First we’ll use a Shuffle CHOP to reorganize our samples into sets of channels, then we’ll use some Math CHOPs to add together our pixel values and to give us some control over the z-displacement, and finally we’ll use a Rename CHOP to make it easy to use this data.

Let’s start this process by connecting our Top to CHOP to a Shuffle CHOP and setting our method to be Sequence Channels by Name:

shuffle

Next we’ll add our Math CHOP and set the combine channel operation to Add, let’s also set the multiply value to 1 /3:

math

Next we’re going to add a slider, and another Math CHOP. Why? Great question. For starters, I want to be able to control the strength of this effect with a slider. At some point I’m going to want to be able to drive the strength of this effect, and a slider is a great way for us to do that. Why another Math CHOP? Another excellent question. While we could just use one Math CHOP and apply our slider there, that also means that there’s no way to isolate the effect of the slider. There’s some redundancy here, but there’s also a little more flexibility in the isolation of applying different alterations to our data set. Is this the best way to code a final component, maybe not, but it is a fine way to work with something that’s still being developed. Alright, let’s add our slider and second Math CHOP:

slider math

Next we need to write a simple expression in our math2 operator in order to be able to use the slider as an input method. On the Multi-Add page we’re going to use the out value from the slider as the value that the incoming channel information is multiplied by – if we think about the structure of our slider’s output we’ll remember that it’s a normalized value ranging from 0 – 1, and we can think of this as being the same as 0 – 100%. Alright, here’s our simple reference expression:

op( ‘slider1/out1’ ) [ ‘v1’ ]

In plain English this expression reads: give me the number value of the channel called ‘v1’ from operator called ‘out1’ that’s inside of ‘slider1’. If you click on the + sign on the bottom right of your slider (making it viewer active) you can now move it left and right to see the change in the number value of your math2 CHOP.

simple referecne expression

Before we move away from this portion of our network we need to add one final operator, a Rename CHOP. The Rename CHOP allows us to rename the channels inside of an operator. Later we’ll want to be able to use this number to replace an value from a surface operator chain – in order to do that easily we need to rename this value. In the to field of the rename CHOP type tz:

rename

 

Surface Operators

Now that we have started the process of converting our Texture into a channel data, we need to think about what we’re going to do with that information. We’re going to start by adding a Grid SOP to our network. We’d like this operator to pull some of its dimensions from the our video – this will make sure that we’re dealing with a surface that’s the correct aspect ratio. In our Grid SOP we’re going to use some simple expressions to pull some information from our Null1 TOP (remember that our Null1 is at the end of our TOP chain). First we’ll use the height and width of our Texture to set the number of rows and columns – we can use the dot call method to ask for the height and width of our TOP with the following expressions for rows and cols:

op( ‘null1’ ).width
op( ‘null1’ ).height

Next we can use internally call the number of rows and columns to for our height and width with the expressions:

me.par.cols
me.par.rows

We’ll also want to make sure that we’ve set our grid to be a Polygon with Rows as the connectivity type.

Now we’ll need to get ready for our next step by adding a CHOP to SOP. This operator is going to allow us to create some geometry out our CHOP data.

chopto

What gives? Well, in order for this operator to work properly, we need to have some feed it some CHOP data.

 

Channel Operators Again

Now we’re finally making progress, even if it doesn’t feel like it just yet. For starters, we have our Texture Operators converted into channel data, we have a piece of geometry that we can alter based on the dimensions of the input Texture, and we’re ready to combine our Channel data with our Surface data, we just have some final house keeping to do.

Let’s start by first converting our Grid SOP to a CHOP with a SOP to CHOP.

sopto

Like we did before we’re going to use a Shuffle CHOP, but this time we’re going to set it to Sequence all Channels:

shuffle2

Next we’ll use a Math CHOP to find the absolute value of our shuffle – we can do this by setting the Channel Pre Op to be Positive:

absolute value

Next we’ll use an Analyze CHOP to find the maximum value coming out of our Math CHOP.

analyze

Now we’re going to normalize our data against itself. We’re going to add another Math CHOP to our network. We’ll connect it’s input to our sopto1 CHOP and in this case we’ll use the Multi-Add page and use 1 / the maxim from our analyze CHOP. We can do this with a simple reference expression:

1 / op( ‘analyze1’ ) [ ‘tx’ ]

All of that should look something like this:

MORE math

We can finally start putting all of this together with one more Math CHOP. This final Math CHOP is going to combine our SOP to string, and our TOP to string. You’ll want to make sure that the SOP string is in the first place on the Math CHOP, with the TOP string coming in underneath. Next make sure that Combine Channels is set to Add, and that Match By is set to Channel Name.

SOP TOP

Now let’s end this set of operations in a Null, and move back to where we left off with our surface operators. Back in our Chop to SOP, let’s set our CHOP reference to be our last CHOP null (in my case it’s Null2). All of that should finally look like this:

chop to 1

At long last we’ve finally transformed a grid in the z direction with the information from an input Texture. Ba da bing bang boom:

grid transformed

 

 

Rendering

Dear flying spaghetti monster help us… this is has been a lot of work, but so far it’s not very fancy. What gives? Well, if we really want to make something interesting out of this, we need to render it – that is, we need to change it from being just some geometric information back into some pixels. If we think back to what we learned while we were playing with Instancing, rendering isn’t too hard, we just need a few things to make it work (some geometry, a camera, and a light source… this time we’ll skip that last one).

Let’s start by adding a camera, and a geometry component to our network.

geo camera

For our render to work properly, we need our chopto SOP to be inside of our Geo. At this point you can use your favorite piece of profanity and get get ready to remake this network OR you can HOLD YOUR HORSES and think about how we might solve this problem. My favorite way to address this kind of issue is to jump inside of the geo component, add an In SOP and set it to render and display. This means that we can pass our geometry into this component without needing to encapsulate all of the geometry inside.

insop

Now let’s connect our chopto to our inlet on the Geo comp:

geo connect

Ideally we want the image from our original texture to be used when rendering our z transformation. To do this, let’s jump back inside of our Geo COMP and add a constant Material. A Constant, unlike a phong, isn’t shaded. In other words, it doesn’t render with shadows. While this isn’t great in some respects, the pay off is that it’s much cheaper to render. While we’re getting started, this is a fine material to start with. We’ll also want to make sure that our Constant is using our original TOP as a color Map. In the Color Map field we can tell this operator to look for the operator called in1 in the directory above with the following call:

../in1

constant mat

Next we need to apply this material to our Geo. To do that let’s jump out of the Geo comp and head to the render page of the parameters window. We can tell our Geo to look for the material called constant1 that’s inside of the geo comp like this:

./constant1

geoconstant

Holy macaroni, we’re almost there. The last step we need to take is to add a Render TOP to our network:

renderTOP

At long last we have finally replicated the z-translation aesthetic that we set out to emulate. From here you might consider changing the orientation of the geo comp, or the camera comp for a more interesting angle on your work.

 

Play Time

That’s all well and good, but how can we turn it up a little? Well, now that we have a portion of this built we can start to think about what the video stream going into this operation looks like, as well as how we modify the video coming out of it. Let’s look at  one example of what we can do with the video coming out.

I’ve made a few changes to our stream above (some simple moving animation, and changed the resolution op), to have something a little more interesting to play with but it’s still not quite right. One thing I want to look at is giving the lines a little more of a neon kind of look and feel. To do this I’m going to start by adding a Blur TOP to my network:

blur

Next I’m going to add an Add TOP and plug both of my TOPs into it, adding the blur back to the original render:

addblur

Finally, I’m going to add a Constant TOP set to black, and a Composite TOP. I’ll composite my Add TOP and my Constant TOP together to end with a final composition:

composite

Now it’s your turn to play. What happens when you play with the signal processing after your render, what happens when you alter the video stream heading into this component. Also, don’t forget that we built a slider that controls the strength of the effect – play and make something fun.

rutrut

 

Looking to take a closer look at what makes this process work? Download the tox file and see what makes this thing tick: rut

Instant Instancing | TouchDesigner

Instant Instance“What if I want ten-thousand. Literally. Ten Thousand.” Back when Wonder Dome was in full swing I had the great honor of meeting some of the folks from Concordia’s Topological Media Lab. While some of their folks were in residence with ASU’s school of Arts Engineering and Media. They’ve spent a significant chunk of time building a system that they call Ozone, which is largely powered by Max MSP and Jitter. While they were visiting with us at Wonder Dome, they had lots of questions about TouchDesigner, how it works and how it was working for us. We talked bout a number of different things that day, but my favorite moment came over lunch. We were talking about making surfaces, and the flexibility and challenges involved. After we had added a sphere to our network, one of the team members asked me “what if I want to make a lot of them. What if I want to make ten-thousand. Literally. Ten Thousand.” There are lots of ways you might do this, but one of my favorite ways to think about making multiple copies of the same object is with instancing.

Say what now?

βατόμουρο / Raspberries by Fir0002/Flagstaffotos

βατόμουρο / Raspberries by Fir0002/Flagstaffotos image by flickr user Duncan Hall

Instancing is a fun way to make lots of copies of a piece of geometry and to place those copies very specifically. On the face of it, that sounds a bit academic. Let’s look at a specific example to unwrap that idea a little bit. Let’s look at a raspberry. We can think of a raspberry in a few different ways. On the one hand it’s a small oval like berry. At the same time if we look closer we can think of this single object as an array of spheres tucked next to one another in a patterned way. Instancing, as a method, allows us to do something like this relatively easily and quickly. On top of that, it’s a ton of fun, and unlocks a whole new set of possibilities when it comes to creating geometry in TouchDesigner.

So where do we start?! Well, we need to start by taking some time to do a little bit of thinking about how instancing works. For starters, instancing is something that you do to a Geometry COMP. As a component, we can do things with Geo’s that we can’t do with regular surface operators. A Geometry COMP is also one of the main ingredients when it comes to rendering surfaces. First we’ll look at how we can work with the Geometry COMP, then we’ll talk about what that means when it comes to rendering.

Okay. Let’s start in an empty network and create a new Geometry COMP.

geo

We could just work with the torus that’s in our Geo to get started, but let’s make a few changes so we have something that’s a little more fun to play with. Dive into your geo, and let’s get situated.

inside the geo

Inside our geo you should only see a single surface operator, a Torus SOP. You should also notice that there’s a little purple dot, and a little blue dot that are in the bottom right hand corner. These are two of the Operator’s flags – the purple dot is the render flag, and the blue dot is the display flag. Flags let you change the behavior of your operators in some interesting ways. The render flag, like it’s name, tells you if something is being rendered or not. Why not render something?! Well, you might find yourself in a situation where you need a SOP to help control the movement of another piece of geometry, but you don’t necessarily want that guiding element to be rendered. In this case you’d want to make sure the render flag is off. The display flag allows a SOP to be seen in the Geometry viewer. Like our other example, there might be a time when you don’t want to display a particular SOP while you’re making a change, in this case you’d want to make sure the display flag is off. There’s lots more to say about Flags, but that should be enough to make you dangerous.

Alright, now that we know a little more about what’s happening in our Geo let’s make some changes. For starters, let’s delete the Torus, and add a Sphere SOP and a Null SOP. Let’s connect these two operators, and make sure that we turn on the display and render flags on the bottom right corner of our Null. While we’re here let’s change the name of our null to DISP for Display.

sphere

Let’s also change the size of our sphere. In the radius parameter field lets change the three values to 0.15.

smaller sphere

Now when we back out of our Geo we should see our sphere instead of a torus.

sphere geo

Alright. Now we’re going to add another sphere to our network, but this time at the same level as our Geo. Let’s also connect that Sphere to a null.

sphere null geo

The next part is gonna start to get funky, so let’s help ourselves out before the world starts to turn upside down on us. Head over to your sphere, and make it viewer active (hit the small + in the bottom right corner), next hit the letter w on your keyboard. What you should now see is the wire frame of your Sphere SOP.

wire sphere

Okay. Let’s just leave that be for now, but know that we’re going to come back to it so we can better understand what’s coming next. Now we’re going to add a SOP to CHOP to our network.

sop to

The SOP to CHOP is a special kind of operator that allows us to change one type of operator to another. In our case, we’re going to change our null1 into CHOP data. To do this, we’re going to grab our SOP null1 and drag it on top of our CHOP sopto1.

soptochop

What manner of witch-craft is this?! Alright, what we’re looking at is the channel information from our SOP. Let’s think back to our wire frame Sphere for a moment. Each one of those intersecting lines represents a point. Each point has three values associated with it in terms of position – x, y, and z. Our SOP to CHOP is giving us a graph that represents all of those points. That’s awesome.

Why is that so awesome? Because now we can instance like there’s no tomorrow. Let’s head over to our Geo COMP and take a look at a few things. If we look at the parameters of this COMP, we’ll notice a page called Instance. Click that bad boy. Here we want to do a few things. First we want to turn on Instancing. Next we’re going to tell our Geo that we’d like to use our CHOP called sopto1. The last thing we need to do here is to help our Geo understand what to do with our CHOP data. In our case we’re going to tell the Geo to use tx for tx, ty for ty, and tz for tz – we’re matching up the location of our points from our Sphere to the points where we’d like instances of our geo. If that doesn’t make sense, that’s okay – for now follow along and this should make more sense soon.

instance

Now if we look at our network we can see some of the magic that’s happening with instancing.

networkinstance

To get a sense of how powerful this really is, let’s go back to our Sphere here in our parent network. In the parameters page, let’s change this sphere from being drawn as a mesh to being drawn as polygons.

polygons

We can now see that our instances are happening at each of the vertices of our polygon. Let’s try one more change to see how this powerful this is. For starters, let’s turn up the frequency count – I’m going to turn mine up to 10. Next let’s add a Noise SOP to our chain of operators between the Sphere and the Null.

noise instance

Now we’re starting to see some magic happen. At this point we’re now transforming the position of our instanced spheres with a noise algorithm that’s being applied to our original geometry.

An Aside About Efficiency 
As a quick note, it’s important to consider that this is not the most efficient way we could have programmed this. In TouchDesigner SOPs are a CPU operation, unless they’re encapsulated inside of a Geo COMP. What does this mean? Well, it means that the noise SOP in our network is a CPU operation, and not a GPU operation and depending on your machine for this example your mileage may vary.

Alright, so now we’ve made something awesome… but how do I use it?! Well, in order to actually use something like this in a project we need to render this geometry. Rendering requires a few different things to be in place, we need something to render (a Geometry COMP), a perspective to render it from (a Camera COMP), and a light (a Light COMP, we don’t always need a light but for now lets add one anyways). Let’s start by adding those COMPs to the network.

render network

Alright, now we can add our final ingredient to our network, a Render TOP. Our render TOP is going to use the three COMPs in our network to actually draw the pixel values of our scene. At this point your network should look something like this:

whole network

Nice work. You’ve not instanced your first set of geometry and rendered it. Now for extra credit, go back and consider changing some of your source SOPs… what happens if you change what’s in your Geo into a box or torus? What happens if you change your Sphere in the parent network into a grid instead? Happy instancing.

noise cubes