Getting and Setting Data in ICE Trees

 
 
 

Almost every ICE tree involves getting data, performing calculations, and then setting data. You can get and set any data using Get Data, Set Data, and other nodes found in the Data Access category of the Tools tab. In addition, there are some compounds for getting and setting specific data in the Getters and Setters subtasks of the Particles and Deformations tasks in the preset manager.

What You Can Get or Set

Types of Data in ICE

There are three types of data you can work with in an ICE tree: intrinsic ICE data, dynamic ICE data, and other scene data.

Intrinsic ICE Attributes

Intrinsic ICE attributes include component attributes that correspond to actual geometric data in the scene, such as PointPosition, PointNormal, PolygonNormal, and so on. Some attributes are read-write, and others are read-only.

Dynamic ICE Attributes

Dynamic attributes include attributes that you create and set "on the fly" and use however you wish in your tree. They do not exist until you set them.

Note that many of the predefined attributes are not intrinsic but actually dynamic attributes that have been automatically set by certain nodes and compounds. These attributes are recognized by their names — for example, the SimulateParticles node recognizes the Force, PointVelocity, and Mass attributes. These predefined attributes always appear in the Get Data node's explorer, even if they haven't been set or initialized yet.

Dynamic attributes also include custom attributes. You can create your own custom attributes for any purpose you wish. Many of the attributes used in the factory compounds are actually custom attributes, such as AgeLimit, Init_PointVelcocity, and others. See Controlling Execution in ICE Trees.

Other Scene Data

In addition, ICE gives you access to other scene data, such as the parameters of any native Softimage property or operator, as well as custom properties.

What You Can Get

You can get any data in the scene. See Getting Data.

What You Can Set

You can set certain data:

  • Some intrinsic attributes, such as PointPosition or EdgeCrease. Other attributes are read-only, like PointNormal and PolygonArea.

  • Any dynamic attribute, including predefined ones like Force, PointVelocity, and so on.

  • Almost any property in Softimage. However, kinematics are special — see ICE Kinematics.

For more details about how to set data, see Beware of ICE Optimizations.

Getting Data, Setting Data, and Context

You can get data by explicit string references or at locations.

  • When you get data by an explicit string reference, you get a set of values with one value for each component. For example, if you get "sphere.PointNormal", you get one 3D vector for each point of the sphere object; in other words, the context is per point of sphere.

  • When you get data at a location, the context depends on the context of the set of locations that is connected to the Source port of the Get Data node. For example, if you start by getting "grid.PointPosition", then use that to get the closest location on sphere, and in turn use that to get PointNormal, the data consists of normals on the sphere but the context is per point of the grid. If instead you started by getting "grid.PolygonPosition", the context would be per polygon of the grid.

You can set data using an explicit string reference only. You cannot set data at locations. To set an attribute, the data must be in the appropriate context. For example, to set PointPosition, the data must be in the per point context of the appropriate object. Not all attributes can be set.

Getting Data

You get data using Get Data nodes. There are several ways to add a Get Data node to your tree.

You can get data before it's been set or initialized and it won't show as an error (red node) until it has been plugged into the rest of the tree.

You can get and set ICE attributes as many times as you like in a tree — each time you get an attribute, you get the latest updated values. However, you can set external data, such as kinematics or a regular property value, only once per tree — if you get it again after setting it, you get the original unchanged values.

To add a Get Data node to an ICE tree

  1. Do one of the following:

    • Drag a Get Data node into the tree from the Data Access category of the Tools tab of the preset manager. The new node's reference is initially blank.

    • Choose Nodes Data Access Get Data. Again, the new node's reference is initially blank.

    • Drag an object, parameter, or other node from an explorer into the tree. Make sure to drag the element's name, not its icon. The Get Data node is pre-filled with the element's reference.

      If the current selection does not have a synoptic or annotation property, you can press F3 in a viewport to open a mini-explorer for the selection and drag from that. Otherwise, you can open the object's mini-explorer using Shift+F3.

  2. Once you have a Get Data node in your tree, you can specify or modify the reference as described in Specifying Scene References.

Getting Data at Locations

In addition to getting data from a string reference, you can get data from locations. For example, you can get PointVelocity at particles' EmitLocation.

To get data at a location, plug any location data into a Get Data node's Source port. When a location is plugged into the Source port of a Get Data node in this way, its Explorer button shows only the attributes that are available at that location.

You can use this technique to get data from other objects using geometry queries like Get Closest Location nodes. For example, you can get PointNormal at the closest location on a sphere. For more information on geometry queries, see Testing Locations.

If an attribute is stored on points, you can still get it at an arbitrary location. The value is interpolated among the neighboring point values. Integer values are interpolated and rounded.

You can convert a location on a geometry into a position (3D vector) by getting the PointPosition attribute at that location.

The positions returned in this way are expressed in the local coordinate system of the object that the ICE tree is applied to (the "Self" object). The same is true of vectors like PointNormal and PointVelocity, but they are handled as vectors rather than as positions (translation is ignored). Custom 3D vector attributes are not converted automatically — it's up to you to decide if they need to be converted as a position, converted as a vector, or left unconverted. For information about converting between reference frames, see Using Geometry Queries.

Getting Data at the Previous Frame

If you need to read attributes or other data from the previous frame, use the Get Data at Previous Frame node. This can be useful if you need to interpolate values between frames.

The important thing to realize about using the Get Data at Previous Frame node is that only the specific data retrieved by that node is evaluated at the previous frame. The following illustrations explain this in more detail.

The tree above calculates the closest locations on the sphere at the previous frame by getting both the point positions and the sphere at the previous frame. It then gets those locations' normals at the previous frame.

The tree above calculates the closest locations on the sphere at the previous frame in the same way as the previous tree. It then returns those locations' normals at the current frame.

The tree above calculates the closest locations on the sphere at the current frame. It then gets those locations' normals at the previous frame.

Be aware that the Get Data at Previous Frame node can have high processing costs, depending on the amount of data that it needs to evaluate at another frame. You can often improve the processing speed of your trees by storing data in custom attributes for use by the next frame, instead of using Get Data at Previous Frame.

Note
  • If points are added and deleted, Get Data at Previous Frame returns the data for the component with the same index, not necessarily the same component. If there are no components with given indices at the previous frame, then the corresponding elements are filtered out of the data set and ignored by the downstream nodes.

  • To use both Get Data at Previous Frame and Set Data with an object, whether it's the self or another one, in the same ICE tree, the object must have a Simulation region in its construction stack. This applies even if you are getting and setting different attributes. Having a Simulation region in the stack means that the lower regions of the stack will be evaluated only on the first frame of the simulation, and subsequent frames will be based on the previous frame — see ICE Trees and the Construction Stack for more information.

Getting Data on Scene Groups

There are special considerations for getting data on groups in the scene:

  • Getting the group itself gets the union of the geometry in the group. For example, you can emit particles from all polygon meshes, surfaces, and curves in a scene group.

  • The other attributes and properties that are available to get from below the group in the Get Data node's explorer are those that exist on each member of the group (intersection). Getting one of these attributes or values returns an array for each member of the requested data set. The size of the array is the size of the group – you can use a Get Array Size node to return this value.

    The order of elements in the array corresponds to the creation order of the members of the group. You can modify this order, if desired. In an explorer, choose View General Sort None (creation), activate View Reorder Tool, and drag and drop nodes within the group. The order is preserved when you save and reopen the scene. For more information, see Sorting and Reordering Elements in the Explorer.

    When getting per-component data, such as PointPosition, the results are correct only when all objects in the group have the same number of components. As a workaround, one possible way to get, for example, all point locations is to plug the Get Data (group) node's value into the Geometry port of a Generate Sample Set node with Emission Type set to Point and Rate Type set to All Points.

As an alternative to using scene groups, you can use the Group Geometry node to combine geometric objects for querying. See Testing Locations.

Reusing Get Data Nodes

You can connect the same Get Data node to as many nodes as you want if you need the same data elsewhere in the tree. However if the data has changed in-between, the Get Data node will return the new data later in the tree.

The Get Self.Foo node returns different values to Stuff and More Stuff because Self.Foo was set in-between.

How Data Is Interpolated at Locations

When you get data at locations:

  • Attributes that belong to points, edges, and samples are interpolated from the surrounding components. The exceptions are certain NURBS-related attributes such as PointBinormal, which are calculated directly at locations on NURBS surfaces and curves.

  • Attributes that belong to polygons and objects are not interpolated. The values returned are always those of the underlying polygon or object.

  • When integers and Booleans get interpolated, they get rounded to the nearest value.

Reference Frames

When you use an explicit string reference to get transformation-dependent attributes such as positions, vectors, rotations, and so on, the raw, untransformed values are returned. These are typically expressed relative to the local space of the object that owns the components. For example, if you get "grid.PointPosition", the values are relative to the grid's local reference frame.

When you get data at a location, the following attributes are automatically converted to the reference frame of the "self" object (that is, the object with the ICE tree):

  • PointPosition

  • PointNormal

  • PointTangent

  • PointBinormal

  • SurfaceGeometricNormal

  • PointReferenceFrame

  • EdgeReferenceFrame

  • PolygonRefFrame

Other attributes are unconverted when you get them at a location. They are expressed in terms of the local reference frame of the object that owns them.

Setting Data

To set data, use the Set Data compound. Simply specify the desired reference and value, either through connections or directly in the property editor. See Specifying Scene References.

Not all attributes can be set. Read-only attributes like NbPoints are not shown in the Set Data node's explorer.

Once you specify a reference, the displayed name of the input port changes from Value to the name of the reference. If you connect a reference to the Set Data node's In Name, it is prefixed to all references defined in the Set Data node itself. This lets you use one Set Data node to set several attributes on the same object. However, when an object name is connected to In Name, you must add ports and specify their references before you can connect values; this is because the object name by itself does not resolve to any data type.

If you set ICE attributes and then get them later in the same tree, you get the modified values. However, you can set external data, such as kinematics or a regular property value, only once per tree — if you get it again after setting it, you get the original unchanged values.

If data has been set for some but not all components in a data set, uninitialized components have default values: zero for most data types, false for Booleans, identity for matrices, black for color, etc.

Attributes whose names begin with two underscore characters ("__") are hidden and not shown in attribute explorers. This can be useful if you have internal "bookkeeping" attributes inside compounds that you don't want users to fiddle with.

Beware of ICE Optimizations

If you try to set data but never use it anywhere in the scene, it never actually gets set because of how ICE is optimized. This applies not only to custom attributes, but also to dynamic attributes — for example, if you try to set PointVelocity but don't use a Simulate node to update point positions, then PointVelocity does not get set.

Among other things, this can have the following consequences:

  • Caches may be missing data that you expect to be there.

  • If you freeze a tree that initializes data before creating another tree that uses that data, the data will be missing.

  • The ICEAttribute.IsDefined property of the SDK is sometimes misleading.

You can force data to be evaluated and set in a couple of ways:

  • Display the data values in the viewport. See Displaying Port Values.

  • Use the data to set real data in the scene, for example, set weight map values or use the data in the render tree.

Initializing Data

To initialize data, simply set it.

To set initial values for particles that have been generated on the current frame, plug a Set Data node into the Execute on Emit, Execute on Spawn, or On Creation port of the appropriate node.

If you can't plug a Set Data node into one of those ports — for example, if you are creating a compound that does one thing to new particles and another thing to old particles — you can filter on the Init attribute. See Automatic Filtering.

Setting Custom Attributes

custom

To create a custom attribute, simply use a Set Data node and make up a new attribute name. For a list of attribute names that are already used in ICE, see ICE Attributes. Don't forget to include the full reference including the object name in the Set Data node, for example, "PointCloud.my_custom_attribute".

You can use custom attributes to store any type of value, including locations. The context and data type of custom attributes are determined by the connected nodes. If the data type is undetermined, the Set Data node is in error (red) — you can use a node from the Constant category to force a specific data type. If the context is undetermined, it defaults to the object context. However, this context can be changed to a component context if you connect nodes that force a different context, as long as there are no conflicting constraints on the context.

Delaying Set Data

The Delay Set Data node holds the results for all Set Data nodes anywhere in the upstream nodes and executes them all at once. This allows you to set attributes that depend on each other. For example, you can swap values.

 

In the first example, the value of A is written to B, and then the value of B (which is now the old value of A) is written back to A again.

At the end, both A and B have the original value of A.

 

With Delay Set Data, B is set to the value of A but it is not written yet. Then A is set to the value of B and both get written together.

At the end, A has the original value of B and B has the original value of A.