Jitter Recipes: Book 4, Recipes 44-49

Recipe 49: RoboMoves

General Principles

  • Animating OpenGL objects
  • Procedural animation technique
  • Working with jit.path for smooth motion


When I made the Humanoid recipe, I quickly found myself looking for a way to set it to motion without having to crank on the trackpad. Having the ability to create a complex animation rig isn’t much fun unless you have a way to make it move. After digging around a little bit in the pile of new Jitter objects, I found my answer in the jit.path object. Since the animation is represented by a Jitter matrix, all the usual techniques for generating, managing, and storing a matrix can be employed. Being able to work with animation loops in this way provides a good mix of randomness with repetition and control.


  • jit.path
  • jit.anim.node
  • jit.gl.light
  • jit.gl.material
  • jit.matrixset
  • jit.gl.gridshape


First, let’s look at the setup inside the “robot” subpatch. The structure of this patch should be familiar to you if you’ve looked at the Humanoid recipe. There is a hierarchy of jit.anim.node objects that provides for all of the articulated joints of our robot. If you haven’t taken time to play with the relationship between @anchor,@position, and @rotatexyz, go ahead and drop in some attrui objects to see how that works.

You might notice the jit.gl.node object at the top of this subpatch. This is there to make it so that we don’t have to type in a context name for each of the GL objects in the subpatch. Using OpenGL implicit contexts in Max 6 isn’t just a good way to save typing, but also makes it easier to reuse patches in other places without having to retype objects.

Okay, now let’s look at jit.path. We’re feeding it the output jit.noise, which is outputting a 4-plane float32 matrix. Before it gets sent to jit.path, the jit.submatrix and jit.concat objects are used to copy the first cell to the right side of the matrix. This will make the looping of our animation more seamless. To loop the animation, we use a counter to send “eval” messages.

It’s worth mentioning that the the output of jit.path is just a list of interpolated numbers. In this case we are using them to drive rotation values for jit.anim.node objects, but these interpolated values could really be used for anything. To get nice fluid motion, we’ve set the interpolation mode to “spline” which interprets the input matrix as handles on a bezier curve

In addition to the random loops created by jit.noise, this patch also stores each loop matrix in jit.matrixset. This allows us to recall previous loops. The point of doing this is to add some amount of repetition and memory to an otherwise completely random setup. Using the ideas set forth in this recipe, along with a more advanced way to generate the animation values, one could make a fairly compelling procedural animation system.

Jitter Recipes: Book 4, Recipes 44-49

Mar 23, 2012 at 3:17am

Thanks. This is just what I have been looking for. But, how would I go about changing the ScrollyBrush, so that it does not scroll. The same features, but no scrolling downwards? Some pointers would be great. I am kind of new to Jitter.

Mar 23, 2012 at 11:12am

Awesome! This is great!

Mar 23, 2012 at 3:20pm

Hi Ricardo. The scroll is controlled by the offset param. You can set it to 0 if you don’t want it to scroll. You can also just delete the ‘nearest’ part of the jit.pix patch and connect “in 2″ directly to the first inlet of “mix”.

Mar 24, 2012 at 6:58am

Thank you so much!!!!!

Apr 11, 2012 at 7:15am

This is great! The thing that mistified me was how to get a continuous line when setting the brush size smaller in Recipe 44?
Setting the brush size smaller leaves a lot of ‘holes’ between’ points, upping the metro doesn’t seem to fix it. What is a solution to this?

thanks, M

Apr 11, 2012 at 4:34pm

Hi Maarten,
Try using much smaller offset values and don’t move the mouse so fast. Smaller brushes cover less area, so it’s harder to maintain a smooth line.

Apr 15, 2012 at 1:00pm

getting the following error on recipe 48

gen_domain: jit.gen: [string "gen1.jit.cpp1"]:431: assertion failed!
jit_gen: Gen patcher not compiled

excited to get it working!

Apr 16, 2012 at 9:09am

Sounds like you are probably using an older Max 6 version. Try updating and see if that clears it up.

May 25, 2012 at 12:58am

I’d love to make this using java or JS :)

Sep 27, 2012 at 9:35am

Hi! and Thank you!
I get the msg from hit.anim.node “doesn’t understand “anchor”"
Any suggestions ? again, Thank you

Dec 10, 2012 at 10:17am

We are trying to use a different input method other than a mouse and we are new to using Max Start. Our project is due on friday so PLEASE HELP ASAP :(

Dec 13, 2012 at 10:26am

@Francisco @anchor was added in an update to Max 6. You might need to upgrade to the most recent available version on the site.

@K and E, The [route mouse] in ScrollyBrush can be replaced with anything that outputs a list of 2 values in a similar range (0-299) if you’d like different inputs to drive brush position

Mar 14, 2013 at 4:00pm

Thank you so much for the patch.

However, I couldn’t seem to find which object is triggering the particle burst. I am trying to sync the burst effect to the beat of the audio signal.

May 22, 2013 at 10:10am

Hi Andrew,

First thanks for your work and contributions!

I want to study your patch deeply because I want to create a similar drawing application but instead of drawing with an airbrush effect I want to do some watercolor realtime drawing.
I’ve found an interesting paper about watercolor simulation on http://grail.cs.washington.edu/pub/papers/curtis-1997-cgw.pdf
How can I start to translating the paper pseudocode into Max? I’m able to code in C++ but I don’t know how to do it using Max objects.
Is possible to open / code in Max without objects and patch cords and do it like other languages but using the Max Runtime?
Any consideration before starting the project?
Is there any better or easy aproach to achieve a watercolor simulation in Max (maybe using OpenGL shaders, Procedural shape growth, etc)?.

I’m quite new to Max environment so sorry if this is a stupid question.

In the other hand, I’ve opened your patch but I can’t get it work!
I’ve downloaded latest Max version 6.1.2 and when I open the patch I get the following errors:

clang: error line 3024 column 10: no matching function for call to "rgb_to_rgba"
jit_gen: Gen patcher not compiled

Why if I get other Gen patches running?
How I can debug the clang error? I’m used to debug apps but I don’t know how to “see” inline code (I’ve only worked in Max with patcher window).

Thanks a lot,


You must be logged in to reply to this topic.