Houdini Engine 6.2
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Attributes

About Houdini Attributes

Houdini has an unparalleled ability to store meta-data. Where geometries are concerned, meta-data can be attached at four possible levels (or owners - HAPI_AttributeOwner):

  1. The geometry itself (detail attributes - HAPI_ATTROWNER_DETAIL).
  2. On each face of the geometry (face attributes - HAPI_ATTROWNER_PRIM).
  3. On each point of the geometry (point attributes - HAPI_ATTROWNER_POINT).
  4. On each vertex of the geometry (vertex attributes - HAPI_ATTROWNER_VERTEX).

This sort of data, whether per geometry, per face, per point, or per vertex, is known as attributes. Attributes may be of int, float, or string types, and they may have any tuple size up to 16, where vector attributes would have a tuple size of 3 or 4.

This ability to store arbitrary data at all levels of the geometry is incredibly powerful, and is one of the key features of Houdini. The use of attributes is so deeply ingrained that point positions are themselves stored as a float point attribute with the reserved name "P" (HAPI_ATTRIB_POSITION) and tuple size of 3. Along with positions, there are many other standard attributes like normals as "N" (HAPI_ATTRIB_NORMAL) and colors as "Cd" (HAPI_ATTRIB_COLOR).

Query Attribute Information

To retrieve or set attribute data you must first know its name. In the case where we want to access the point positions, the name is known to be the pre-defined name "P", or "N" for the normals. However, in the more general case, you might want to query a geometry to see what sort of attributes have been attached to it. To do this call HAPI_GetAttributeNames(). The number of attributes of a specific HAPI_AttributeOwner is stored as an appropriate count on the HAPI_PartInfo.

Once we know the name of the attribute that we wish to retrieve the data for, the next step is to get some information on by calling HAPI_GetAttributeInfo() and filling a HAPI_AttributeInfo struct. Always check HAPI_AttributeInfo::exists before trying to use it.

The HAPI_AttributeInfo::typeInfo can help identify the purpose of the data stored in the attribute, without relying solely on its name. For example, Textures coordinates will have a type set to HAPI_ATTRIBUTE_TYPE_TEXTURE while normals will have the HAPI_ATTRIBUTE_TYPE_NORMAL.

Getting Attribute Values

Assuming you have a filled HAPI_AttributeInfo as described in Query Attribute Information, the HAPI_AttributeInfo::storage, HAPI_AttributeInfo::count, and HAPI_AttributeInfo::tupleSize tell you everything you need to know to allocate an appropriately sized buffer to hold the attribute data. For example, to retrieve point positions from a geometry with 100 points, the HAPI_AttributeInfo::storage would be HAPI_STORAGETYPE_FLOAT, the HAPI_AttributeInfo::count would be 100, and the HAPI_AttributeInfo::tupleSize would be 3. Consequently, we would allocate a buffer to hold 100 * 3 floats. Once the appropriate type and size buffer has been allocated, the data can be retrieved with a call to the appropriate getter function:

Array attributes can also be queried, but need special consideration. Each entry in an array attribute is an array of variable size, therefore it is essentially a multidimensional array. The total count of all array values is stored in HAPI_AttributeInfo::totalArrayElements. Note that in this case the HAPI_AttributeInfo::tupleSize is only for use as metadata, such as for displaying as a vector in the UI. Instead, the sizes of each entry need to be returned as an array as well, where each element in the sizes array specifies the length of each array entry in the attribute. The sizes array will be of HAPI_AttributeInfo::count length. The attribute data values are returned as a flattened array where each entry's array values are stored through depth-first traversal. Use the sizes array to recreate the multidimensional array structure.

Sample code showing querying array attributes:

hapiTestSession,
geo_node_id, 0,
attribute_name,
owner,
&attribute_info );
assert( result == HAPI_RESULT_SUCCESS );
std::vector< int > data(
attribute_info.totalArrayElements );
std::vector< int > sizes(
attribute_info.count );
hapiTestSession, geo_node_id, 0,
attribute_name,
&attribute_info,
data.data(),
(int)attribute_info.totalArrayElements,
sizes.data(),
0, attribute_info.count );
assert( result == HAPI_RESULT_SUCCESS );
// Check the data and sizes
// The example asset sets the array attribute values like so:
// [0]
// [0, 1]
// [0, 1, 2]
// [0, 1, 2, 3]
int idx = 0;
for (int i = 0; i < attribute_info.count; ++i)
{
assert(i + 1 == sizes[i]);
for (int t = 0; t < sizes[i]; ++t)
{
assert(t == data[idx]);
idx++;
}
}

Adding Attributes

Attributes can only be created on input assets. See Marshalling Geometry Into Houdini.

To create an attribute first create and initialize a HAPI_AttributeInfo struct. You can use the HAPI_AttributeInfo_Create() helper function to initialize. Make sure you set all fields in this struct appropriately given your geometry.

Using the HAPI_AttributeInfo, create a new attribute using HAPI_AddAttribute().

Setting Attribute Values

Mirroring the getter equivalents, here are the attribute setters:

For example, the follow code snippet from the Maya plugin adds the position "P" attribute onto the input geometry, then proceeds to push the actual points into Houdini Engine via HAPI_SetAttributeFloatData():

HAPI_AttributeInfo pos_attr_info;
pos_attr_info.exists = true;
pos_attr_info.owner = HAPI_ATTROWNER_POINT;
pos_attr_info.count = meshFn.numVertices();
pos_attr_info.tupleSize = 3;
nullptr,
myInputAssetId,
myInputObjectId,
myInputGeoId,
"P",
&pos_attr_info );
nullptr,
myInputAssetId,
myInputObjectId,
myInputGeoId,
"P",
&pos_attr_info,
meshFn.getRawPoints( NULL ),
0,
meshFn.numVertices() );