Working with Arrays in ICE Trees

A data set may be composed of single values or arrays. An array is an ordered set of values of the same data type. Among other things, arrays are used to implement particle strands.

Arrays are zero-based. This means that in an array of size 5, the first element has index 0 and the last element has index 4.

NoteNote that the Build Array node has inputs called Value1, Value2, and so on, but these are just the names of the ports. The array indices are 0, 1, etc.

Arrays may have different sizes for different members of the same data set. For example, Get Closest Points may return a different number of locations for each position depending on how many points are within the cutoff distance.

Many of the basic nodes support arrays in addition to single values, including nodes in the Math and Conversion categories. There is also a set of nodes that allow building and modifying arrays; for example, the Push On Array node adds a value at the end of the array. There are also nodes that access array attributes such as the size of the array, the average of the values, etc.

The nodes in the Array category are used to perform the standard array operations: popping, pushing, removing, and so on. See the sections below for special notes on specific nodes.

Array Size

Arrays are dynamic — they automatically change size when you insert, remove, pop, or push items.

However, if you know the maximum size that the array will grow to in advance, you can improve performance by using the Reserve Array node to reserve memory for it, for example, in a separate ICE tree earlier in the construction stack that does not get re-evaluated during a simulation. You can also use Reserve Array to reserve additional memory for existing arrays. For example, if you are about to push four items into every array in a data set, it may be more efficient to reserve the memory first. Reserving memory does not change the size of arrays.

The Resize Array node from differs Reserve Array in that it does change the array size. If the new size is larger, new elements are filled with default values.

Inserting into Arrays

In addition to using the Insert in Array node to insert a value into an array, you can use it to insert an array into another array. This is like splicing one array inside another beginning at the specified index.

Selecting Items in Arrays

The Select in Array node returns the item in an array at a specified index value. You can also connect an array of index values to return an array containing the specified items.

Sorting Items in Arrays

There are two nodes for sorting arrays:

  • Sort Array rearranges the items in the array in ascending or descending order. It uses the same criteria as the Compare node — see Working with Transforms.

  • Sort Array with Key sorts one array based on another of the same size. It is similar to sorting the rows of a table or spreadsheet based on one of two columns — the other column is rearranged in the same way.

Note that you cannot sort arrays of locations or custom user data blobs.

Getting Array Indices

The Get Array Sub Indices node simply returns an array of the integer indices used by another array. This is typically used with Sort Array with Key. For example, if you have an array of deformers and an array of point weights and you want to get the two deformers with the strongest influence, you can get the indices of the deformer array, sort it according to the point weight array (using descending order), and then return the first two indices.

Accessing Arrays at Invalid Indices

If you use invalid index values with the array nodes, such as index values that are negative or that are greater than or equal to the array size, then the result is filtered. In some cases, for example when using Set in Array, this can result in the entire array being filtered for those elements in a data set.

Combining Arrays and Non-arrays

You can combine arrays with single values. For example, adding a single scalar value to an array of scalars adds the value to every item in the array. Similarly, muliplying an array of vectors by a scalar multiplies every vector in the array by the scalar.

Operating on Multiple Arrays

When combining arrays using operators, for example, when adding, multiplying, or comparing arrays, the operation is performed item by item. For example, when adding two arrays, Value1[0] is added to Value2[0] to give Result[0], Value1[1] is added to Value2[1] to give Result[1], and so on.

If the arrays are of different sizes, any "overflow" is filtered and the output is the same size as the smallest input array. The same is true for the If node when the Condition, If True, and If False inputs are arrays of different sizes, and for the Select Case node when its inputs are arrays of different sizes.

2D Arrays

The Array2d compounds mimic an array of subarrays. This category is available on the Tools tab of the preset manager

Internally, 2D arrays are implemented as two separate array attributes:

  • 2darray is a linear concatenation of all the subarrays.

  • 2darrayids is an array of integers that stores the last index of each subarray in 2D array.

If you use more than one 2D array on an object, you must rename these attributes in the Build 2D Array compound and make the corresponding name changes in the other compounds that work with 2D arrays. Otherwise, the different 2D arrays will overwrite each other. Apart from that, you can use the Array2d compounds without worrying about how they work internally.

The general workflow for 2D arrays is:

  1. Build standard arrays using the standard array nodes.

  2. Assemble arrays into 2D arrays using Build 2D Array.

  3. To get and work with values from a 2D array, use Select SubArray in 2D Array and then use standard array nodes.

  4. To change values in a 2D array, use Set SubArray in 2D Array.