Attributes

Attributes are containers for data associated with a GeoInfo in NUKE. NUKE allows for per-point, per-vertex, per-primitive and per-object attributes. These are described in the Attribute groups section. Attributes can also hold different types of value. We go into this in the as described in the Attribute types section.

Although attributes belong to individual GeoInfo objects, they are stored as part of a GeometryList so that they can be packed and accessed more efficiently.

Attribute groups

There are 6 attribute groups in NUKE’s 3D system:

Primitives
The shapes which make up the object. These can be triangles, individual points, polygons, and so on.
Vertices
A point on a primitive. Vertices aren’t shared between primitives, but they don’t store a position directly - instead they have an index into the points list. So primitives cannot share a vertex, but they can each have a vertex that exists at the same point in space.
Points
Coordinates of points in 3D space, usually stored in the object’s local coordinate system.
Object
A single 3D object.
Matrix
The transformation matrix from the object’s local coordinate system to world coordinates.
Attributes
Any other data associated with the object. Attributes themselves are associated with one of the other groups, which will determine the cardinality of the attribute. To put it another way, a point attribute will have one item per point; a vertex attribute will have one item per vertex; and an object attribute will only ever have one item.

These groups are defined by an enum in GeoInfo.h:

enum GroupType {
  Group_None       = -1,
  //
  Group_Primitives = 0,
  Group_Vertices   = 1,
  Group_Points     = 2,
  Group_Object     = 3,
  //
  Group_Matrix     = 4,
  Group_Attributes = 5,
  //
  Group_Last = 6
};

The special value Group_None is used to indicate an unknown or invalid group; Group_Last will always be the total number of groups and is useful for defining array sizes or when iterating over all groups (for example).

There’s also a set of bitmasks defined for the groups. These are mainly used for the rebuild flags on the object. They are defined in GeoInfo.h like this:

enum {
  Mask_No_Geometry  = 0x00000000,
  Mask_Primitives   = 0x00000001, //!< Primitive list
  Mask_Vertices     = 0x00000002, //!< Vertex group
  Mask_Points       = 0x00000004, //!< Point list
  Mask_Geometry     = Mask_Primitives | Mask_Vertices | Mask_Points,
  //
  Mask_Object       = 0x00000008, //!< The Object
  Mask_Matrix       = 0x00000010, //!< Local->World Transform Matrix
  Mask_Attributes   = 0x00000020, //!< Attribute list
  //
  Mask_All_Geometry = Mask_Geometry | Mask_Attributes | Mask_Object | Mask_Matrix,
};

typedef unsigned GeometryMask;

Note that some of the flags are just combinations of others, defined for convenience: Mask_Geometry and Mask_All_Geometry.

Attribute types

These are the attribute types NUKE knows about:

Float
A single floating point value.
Vector2
A pair of floats.
Vector3
Three floats.
Vector4
Four floats.
Normal
Three floats, like a Vector3, but transformed differently.
Int
A single integer value.
String
A char* value. TODO: does NUKE manage the memory for these or is it up to client code?
Pointer
A void* value. You can use this to store a pointer to any data you like; NUKE will never try to do anything with these other than passing them along the DAG for you. This means you have to manage the memory it points to yourself.
Matrix3
A 3x3 matrix, 9 floats altogether.
Matrix4
A 4x4 matrix, 16 floats altogether.

There’s an enumeration defining these types in DDImage/Attribute.h:

/*! Attribute data type enumerations. */
enum AttribType {
  INVALID_ATTRIB = -1, //!< Data type not set

  FLOAT_ATTRIB,   //!< 1 float
  VECTOR2_ATTRIB, //!< Vector2(2 floats)
  VECTOR3_ATTRIB, //!< Vector3(3 floats)
  VECTOR4_ATTRIB, //!< Vector4(4 floats)
  NORMAL_ATTRIB,  //!< Normal vector - Vector3(3 floats)

  INT_ATTRIB,     //!< Int
  STRING_ATTRIB,  //!< Char*
  POINTER_ATTRIB, //!< Void*

  MATRIX3_ATTRIB, //!< Matrix3 (9 floats)
  MATRIX4_ATTRIB  //!< Matrix4 (16 floats)
};

Attribute contexts

An Attribute object in the NDK is merely a data store: it knows the type and number of values it holds, its name and nothing else. It doesn’t have any information about its wider context, such as the attribute group it belongs to. DDImage provides the AttribContext class to handle this.

An AttribContext contains an Attribute, a group type (e.g. Group_Points, Group_Vertices and additional information about how the attribute is to be processed such as whether it should be interpolated or not.

Finding out what attributes are available

The GeoInfo class has two methods to help find out what attributes it has:

int GeoInfo::get_attribcontext_count() const

Get the number of attributes (and hence the number of AttributeContext objects) on this GeoInfo.

const AttribContext* GeoInfo::get_attribcontext(int index) const

Get an AttribContext using it’s list position rather than it’s name, type and group.

Using these you can iterate over all the available attributes for a GeoInfo.

Getting attributes

The GeoInfo class provides read-only access to all of its attributes via various lookup methods, detailed below. Some of these methods allow you to specify a group for the attribute; others do not. For the methods where you don’t specify a group it will search through a number of the groups in the following order:

  1. Group_Vertices
  2. Group_Points
  3. Group_Primitives
  4. Group_Object

The GeoInfo class provides the following methods for getting an Attribute:

const Attribute* GeoInfo::get_attribute(const char* name) const

Returns an Attribute with the specified name and any type, using the search order above.

const Attribute* GeoInfo::get_typed_attribute(const char* name, int type) const

Returns any Attribute with the specified name and type, using the search order above. If there is an attribute with a matching name but a different type, this will return NULL.

const Attribute* GeoInfo::get_group_attribute(int group, const char* name) const

Returns an Attribute, if one exists, with the specified name and any type. This will only look in the specified group and will return NULL if it doesnt’ find one there.

const Attribute* GeoInfo::get_typed_group_attribute(int group, const char* name, int type) const

Returns an Attribute, if one exists, with the specified name and type. This will only look in the specified group and will return NULL if it doesn’t find a matching attribute there.

There are equivalent methods for getting an AttribContext:

const AttribContext* GeoInfo::get_attribcontext(const char* name) const

Returns an AttribContext with the specified name and any type, using the search order above.

const AttribContext* GeoInfo::get_typed_attribcontext(const char* name, int type) const

Returns any AttribContext with the specified name and type, using the search order above. If there is an attribute with a matching name but a different type, this will return NULL.

const AttribContext* GeoInfo::get_group_attribcontext(int group, const char* name) const

Returns an AttribContext, if one exists, with the specified name and any type. This will only look in the specified group and wil return NULL if it doesn’t find one there.

const AttribContext* GeoInfo::get_typed_group_attribcontext(int group, const char* name, int type) const

Returns an Attribute, if one exists, with the specified name and type. This will only look in the specified group and will return NULL if it doesn’t find a matching attribute there.

Adding attributes

To add an attribute to an object, use:

const AttribContext* GeoInfo::writable_attribcontext(int obj, GroupType group, const char* name, AttribType type) const

Get or create an attribute on a particular object and return an AttribContext for it. The AttribContext will have the group ID, attribute name and item type specified by the group, name and type parameters respectively.

Deleting attributes

The GeoInfo class provides this method:

void GeoInfo::delete_group_attribute(int group, const char* name, int type=INVALID_ATTRIB)

If you leave the type set to the default value, INVALID_ATTRIB, it will not take the attribute type into consideration when finding the attribute to delete. Otherwise, it will only delete an attribute of that type.

Standard attributes

There are a number of predefined attributes that NUKE recognises:

Attribute name Group Meaning
“uv” Group_Points Group_Vertices Texture coordinates, stored as a vector4.
“N” Group_Points Group_Vertices Group_Primitives Point, vertex and surface normals stored as a vector4.
“Cf” Group_Points Surface colour.
“pw” Group_Points World-space point.
“vel” Group_Points Per-point velocity, used by the ScanlineRenderer for motion blur.