Select Page

Colour Variation with the Instancer and Arnold

Using Arnold, it’s extremely easy to add colour variations to particle/ MASH instances. This works in a similar way to the MASH Colour node, which is only available when using MASH in Repro mode (when the output is a mesh). When you’re working with instances, the job of colour variations is down to the renderer.

Here’s how the workflow works in Arnold:

Create a MASH network (Instancer mode) with a Sphere
Add an aiStandardSurface to your Sphere
Add an aiColorJitter to the Color attribute of your shader.
Set a color for Input
Under the Object rolldown set values for Hue Min and Hue Max

You should now see colour variation across your spheres when you render the scene (remember to add a light!).

You can also add the effect per face as well as per object (the image below does both) so each leaf has a slightly different colour:

Initial State with Visibility

When using Initial State transforms in MASH, it’s possible to also inherit the visibility of those transforms and get them into the MASH network using this simple Python script.

Just a note, this only works with the Transform mode of Initial State (see screenshot).

Script below, I appreciate it could be shorter, but I’m trying to make it obvious what’s happening 😉


Adding Colour to Volume Noise in Maya

Suppose, for whatever reason, you want colourised noise in Maya; there are some 3d shaders that are colour based, like Crater, or Mountain, but if you want a colour version of Volume noise for example, there’s no support for that out the box, so in order to achieve this, you need to remap tones of grey into colour. To do this you simply add a remapColor node.

Here’s an example of how a finished setup would look (this is the setup for the above image):

Using Velocity in MASH

Using velocity to scale MASH points

MASH measures the velocity of all the points travelling in a network. To see the speed of your objects you can add a Points node and set the mode to Velocity, you will then see each point’s velocity printed in the viewport:


So how about a practical use for this, well, the Colour node has a build in ‘Use Velocity’ checkbox, which will use an object’s velocity as a multiplier for the colour, so slow objects are dark, and fast objects are bright.

But if you want to move on to something more complex, you need to add the Python node, rest assured, this couldn’t be easier.
The following script will scale objects according to their speed, it was used to produce the above animation.

  1. Add a Python node
  2. Copy and paste the script into it.

The available channels are:

  • md.velocity: A list of translational magnitudes (the speed of the point’s movement)
  • md.angularVelocity: The same thing but for rotation.
  • md.velocityVec: A tuple containing the magnitudes for each axis (x, y, z)
  • md.angularVelocityVec: The same thing but for rotation.

Their corresponding output arrays (though I don’t know why you’d want to set these!) are:

  • md.outVelocity
  • md.outAngularVelocity
  • md.outVelocityVec
  • md.outAngularVelocityVec

The Papers Behind The World Node

The World Node has three distinct types of distribution.

  • Clusters – where points are placed in clusters around other points.
  • Map based – where points are distributed according to a density in a map.
  • Terrestrial ecosystems – where an ecosystem is simulated.

I’ve been asked a number of times which paper I based the terrestrial ecosystems simulations on, so this post will look into that. The truth is that I read around 20 papers when creating this node (23 to be exact!), but one in particular kicked it all off.

Where it started

It all started when Andrew Camenisch, of Mudbox fame, sent me this paper: Guided Ecological Simulation For Artistic Editing. It’s a great document that talks about the implementation of cutting edge ecosystem simulation algorithms. The algorithms mentioned in that paper can be found here: Ground Cover and Vegetation in Level Editors. This really is an excellent, clear and complete paper which can be summarised, haphazardly, like so:

  1. Put some seeds on the ground.
  2. These seeds grow up over time.
  3. At a certain age they start dropping their own seeds.
  4. These seeds may or may not survive depending on where they land/ what resources are available.
  5. The surviving seeds grow up, and at a certain point drop their own seeds.
  6. Plants can die if they are starved of resources.
  7. Plants die when they get too old.

This is a major over simplification, but you get the picture. I decided to start doing some experiments on implementing these ideas — done on my commute to work of course — and these produced some really cool results, so I decided to just go ahead and turn it into a fully fledged MASH node.


In order to provide artistic control over the simulation, and to make it production worthy, it needed a few extra controls, these included:

  • Avoidance meshes and curves.
  • Id maps – for dictating what type of seed was planted where.
  • Maps for soil conditions (such as moisture and soil quality).
  • Mesh normal sampling for slope awareness (some genotypes might not like ground that is too steep).
  • Sparcity controls.
  • Sun/ shade controls.

On top of those there were a few additions that resulted in more realistic outcomes, including using sigmoidal curves for the growth rate and various quadratic curves for resilience and other genotype characteristics.

Almost everything in the above list is optional, meaning you can go from an empty scene to a basic forest in about 30 seconds. All the advanced stuff needs turning on.

Faster, faster, faster

There was however a problem; once you enabled all these things, everything started taking a bit more time then I deemed acceptable – and once I’d optimised all the additional features as much as possible, there was only one place to go, the algorithm itself. So I started experimenting with which bits of the simulation I could approximate, or what, given certain circumstances, could be skipped. The result is what we’ve ended up with in the shipping product, which gives a result of virtually the same quality and is about 2.5x faster then the original algorithm, so while it isn’t an exact implementation of the above paper, you shouldn’t really notice the difference.

Additional reading

To anyone who’s interested in this topic, content in these papers also resulted in code additions/ changes:

Effects of size, competition and altitude on tree growth 
David A. Coomes and Robert B. Allen

Extended Competition Rules for Interacting Plants
Monssef Alsweis

Generating Spatial Distributions for Multilevel Models of Plant Communities
Brendan Lane and Przemyslaw Prusinkiewicz


Setting MASH Point positions with JSON

A while ago I was asked by how you can set MASH points using JSON – a fairly specific request, but it’s pretty easy because the MASH Placer node uses a JSON dictionary to store it’s painted points, so we can tap into that to set the positions (and scale, and rotation and Id).

The JSON data is just some nonsense I made up, you can obviously use whatever you’d like here and make this as complex or simple as you’d like.

An alternative approach to this would be using the Python node and translating Python to MASH points in there, the disadvantage of this though is that the Python node recalculates every frame, which is unnecessary for this task (note: you can disconnect the Python node from the Time node to stop this behaviour so as is often the case with MASH, there’s more then one way to do this).



MASH & Python & meshes – Part 2: Colour Sets

Following on from part 1, in this example we take things a small step further. Instead of just sampling the mesh for the closest normal to the MASH point, we sample the mesh for the closest point and normal, this call has the added benefit of also returning the closest face to the MASH point. Once we have the closest face we can use the MItMeshPolygon class to give us colour information about that face. I appreciate MFnMesh can also give us the information we want here, I’m just showing one of many ways of doing this.

This is a fairly simplistic example of using colour sets, meshes of course can contain multiple colour sets, and these can be set via methods on MFnMesh so with a little extra work (left to the reader) you can read multiple colour sets if you wish.

This script also includes the normal sampling from the previous script, and as before, you can just copy and paste this Python script onto the Python node and hit the run button, make sure your MASH network has a mesh based distribution, otherwise there will be no mesh to sample.


MASH & Python & meshes – Part 1: Normals

There are many reasons you might want to access mesh information in a MASH network, we’ll take a look at two of those reasons here.

  • In part 1 we’ll look at turning points off based on mesh normals.
  • In part 2 we’ll look at setting point Ids based on mesh vertex colours.

For the mesh normals, the process is fairly easy, we ask the MASH API to give us the Distribute node of the network, we then ask the Distribute node for the mesh you’re distributing on, once we have that mesh, we query the closest normal to the MASH point. The end goal here is to say ‘if the mesh normal is pointing more then 20 degrees away from up, turn the point off’. In the above images this has the effect of turning the trees off on steep slopes.

Check out the script. You can copy and paste this onto any Python node (make sure your MASH network has a mesh distribution, otherwise there will be no normals to sample!).

The World node has this ‘slope’ filtering built in, but this kind of technique is useful if you aren’t using that node (for whatever reason, e.g. you want to have a completely manual placement via the Placer node, or you want a more random scattering via the Distribute node).

If performance is important to you, I highly recommend investigating the MMeshIntersector class and using that instead of MFnMesh’s closest normal command as the mesh intersector is a lot faster at this task (it takes a bit more setup which would confuse the example, so I haven’t used it here).


Accessing MASH Point Data with the Maya API

Good news, MASH only uses Maya’s default data types, so all MASH data can be accessed via normal Maya APIs.

Ordinarily this isn’t needed as MASH provides two built in ways to extract data:

  1. For the non scripter there’s the Breakout node, which can feed MASH data into float/vector attributes in Maya via connections.
  2. The Python node gives users access to the raw data which they can extract and manipulate in any way they like.

However, for the performance conscious, or for those wanting to write their own MASH nodes or export MASH data in some custom/ game engine format, it might help to know a few things about Maya’s data types and APIs, so here are some simple recipes to get you going. In the following example we’ll get a MASH node (a Waiter), get it’s output data, and print a list of all the channels it contains along with the MASH point positions.

Before we get started, please remember, data getting/setting in Maya should only be done with connections otherwise Parallel Evaluation performance will suffer, so what I’m about to show you should never be run in an expression node.

MASH Data can only be extracted with either the CAPI or PyAPI 1.0. The PyAPI 2.0 isn’t finished yet and thus can’t be used with MASH.

Step 1: Get the MObject for the MASH node.

Step 2: Get a list of channel data and print it.

Step 3: Get a specific channel. In C++ getting the channel data type is trivial, however I’ve never managed to do this in Python (it seems the data type enum get’s mangled when the Python API is auto-generated), so a bit of educated guessing on your part may be needed.

A. Double channel eg. Visibility.

B. Vector array, e.g. Position.
First we need a function to copy the MVectorArray into a Python list:

Now we can use that to get the data:

And you’re done. In C++, everything’s easier, you would check the channel data type first like so and then just copy the array:

Any questions let me know.







MASH API Examples

Maya 2017 Update 3 includes a new API to help quickly create MASH networks with Python. Below are 4 examples that will hopefully get you started. To use them, copy and paste the Python into the Script Editor, and then run the script. signalcolour

Morphing from a Torus to a Sphere using a Volume Axis Field for Turbulence. This project is pretty cool as it shows how to use Flight to do something completely unrelated to flocking, it’s essentially being hijacked and turned into a particle system (the align/cohere/separate/ gravitate strengths are all set to 0). The ability to plug a particle field into Flight is also new in Update 3. merge-flight-field


Parquet Flooring. There are many ways to do this kind of thing with MASH (I can think of at least 8), this method uses the Symmetry and Replicator nodes. It’s not really that useful, but it might inspire. symmetryreplicator