Houdini Engine 3.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Migration from HAPI 2.0 to HAPI 3.0

What's New in HAPI 3.0


  1. (New) HAPI_ThriftServerOptions struct added for better argument management.
  2. (Modified) HAPI_StartThriftSocketServer() and HAPI_StartThriftNamedPipeServer() will now take the new HAPI_ThriftServerOptions struct containing the port and timeout instead of separate parameters.


  1. (Modified) HAPI_SetEnvFiles() removed in favor of a new houdini_environment_files parameter on HAPI_Initialize().
  2. (New) HAPI_CookOptions::extraFlags member added for internal use.


  1. (New) HAPI_ComposeNodeCookResult(), HAPI_GetComposedNodeCookResult(), and HAPI_CheckForSpecificErrors() added to help with getting errors and warnings on specific nodes.
  2. (New) HAPI_ErrorCode enum added for use with HAPI_CheckForSpecificErrors().


  1. (New) All HAPI transforms now have shear support.
  2. (New) HAPI_SHEAR_VECTOR_SIZE define added for shear support.
  3. (New) HAPI_Transform::shear[] added for shear support.
  4. (New) HAPI_TransformEuler::shear[] added for shear support.


  1. (Removed) HAPI_AssetId typedef removed since it is now just a HAPI_NodeId.
  2. (Removed) HAPI_AssetInfo::id member since it is now just a HAPI_NodeId and that is already stored in HAPI_AssetInfo::nodeId.
  3. (Removed) HAPI_AssetType enum removed in favor of the HAPI_NodeType enum.
  4. (Removed) HAPI_AssetSubType enum as the distinction is no longer relevant.
  5. (Removed) HAPI_AssetInfo::type and HAPI_AssetInfo::subType remove as they are no longer used.
  6. (Removed) HAPI_AssetInfo::validationId removed in favor of HAPI_NodeInfo::uniqueHoudiniNodeId.
  7. (Removed) HAPI_IsAssetValid() removed in favor of the new HAPI_IsNodeValid().
  8. (Removed) HAPI_InstantiateAsset() removed in favor of HAPI_CreateNode().
  9. (Removed) HAPI_CreateCurve() removed in favor of HAPI_CreateNode().
  10. (Removed) HAPI_CreateInputAsset() removed in favor of HAPI_CreateInputNode().
  11. (Removed) HAPI_DestroyAsset() removed in favor of HAPI_DeleteNode().
  12. (Modified) HAPI_GetAssetInfo() now takes a HAPI_NodeId instead of HAPI_AssetId.
  13. (Removed) HAPI_CookAsset() now removed in favor of HAPI_CookNode().
  14. (Removed) HAPI_GetAssetTransform() removed in favor of HAPI_GetObjectTransform().
  15. (Removed) HAPI_SetAssetTransform() removed in favor of HAPI_SetObjectTransform().
  16. (Removed) HAPI_GetInputName() removed in favor of HAPI_GetNodeInputName() for node inputs and HAPI_GetParmInfo(), then getting the HAPI_ParmInfo::nameSH, for inputs that are actually exposed node path parameters.
  17. (Removed) HAPI_GetEditableNodeNetworks() and HAPI_AssetInfo::editableNodeNetworkCount removed in favor of HAPI_ComposeChildNodeList().
  18. (Modified) HAPI_AssetInfo::geoInputCount only lists node inputs. Object path parameters are not counted in this anymore.

HIP Files

  1. (Removed) HAPI_CheckForNewAssets() and HAPI_GetNewAssetIds() have been removed in favor of HAPI_ComposeChildNodeList() and HAPI_GetComposedChildNodeList() called on the HAPI_NODETYPE_OBJ manager node with recursive set to false.


  1. (New) HAPI_NodeType enum added to replace the HAPI_AssetType enum.
  2. (New) HAPI_NodeInfo::type member added to store the node type.
  3. (New) HAPI_NodeInfo::parentId member added to easily get a node's parent node id.
  4. (New) HAPI_IsNodeValid() added to replace HAPI_IsAssetValid().
  5. (New) HAPI_GetNodePath() added to more easily get absolute or relative node paths.
  6. (New) HAPI_GetManagerNodeId() added to get the HAPI_NodeId for any top-level manager node (ie. "/obj").
  7. (New) HAPI_ComposeChildNodeList() and HAPI_GetComposedChildNodeList() added to make it easier to get a filtered list of child nodes under any node. Replaces HAPI_GetNodeNetworkChildren().
  8. (Removed) HAPI_GetNodeNetworkChildren() removed in favor of HAPI_ComposeChildNodeList() and HAPI_GetComposedChildNodeList().
  9. (Modified) HAPI_CreateNode():
    1. Is now an asynchronous function.
    2. Will now accept output from HAPI_GetAvailableAssets() which is the fully qualified name of the node and operator table. For this workflow, the parent_node_id should be -1.
  10. (New) HAPI_CreateInputNode() added to replace HAPI_CreateInputAsset().
  11. (New) HAPI_CookNode() added to be able to cook an individual node, which includes asset nodes.
  12. (New) HAPI_GetNodeInputName() added to get the name of a node input.


  1. (Modified) HAPI_PARMTYPE_PATH_NODE was changed to HAPI_PARMTYPE_NODE.
  2. (New) HAPI_PARMTYPE_FOLDERLIST_RADIO enum added for the new radio tabs support.
  3. (New) HAPI_ParmInfo::tagCount member added for tags support.
  4. (New) HAPI_GetParmTagName() added to get a parameter tag name on a parameter.
  5. (New) HAPI_GetParmTagValue() added to get a parameter tag value on a parameter tag.
  6. (New) HAPI_ParmHasTag() added to quickly check if a parameter has a specific tag.
  7. (New) HAPI_GetParmWithTag() added to quickly find a parameter with a specific tag.
  8. (New) HAPI_GetParmNodeValue() and HAPI_SetParmNodeValue() added to get/set a HAPI_NodeId given a node path parameter, instead of just getting the node path string. These replace HAPI_ConnectAssetTransform, HAPI_DisconnectAssetTransform, HAPI_ConnectAssetGeometry, and HAPI_DisconnectAssetGeometry.
  9. (New) HAPI_ParmInfo::typeInfoSH member will now also indicate the OP node filter on OP node path parameters.
  10. (New) HAPI_ParmInfo::inputNodeType and HAPI_ParmInfo::inputNodeFlag members added to easily get the node type and flags linked by a OP Node path parameter.


  1. (Modified) HAPI_GetHandleInfo() and HAPI_GetHandleBindingInfo() now take a HAPI_NodeId instead of a HAPI_AssetId.


  1. (New) HAPI_ObjectInfo::isInstanced member added to easily tell if an object node is being instanced.
  2. (New) HAPI_ATTRIB_INSTANCE define added for the "instance" attribute name.
  3. (Removed) HAPI_ObjectId typedef removed since it is now just a HAPI_NodeId.
  4. (Removed) HAPI_ObjectInfo::id member since it is now just a HAPI_NodeId and that is already stored in HAPI_ObjectInfo::nodeId.
  5. (Removed) HAPI_GetObjects() removed in favor of HAPI_ComposeObjectList() and HAPI_GetComposedObjectList().
  6. (Removed) HAPI_GetObjectTransforms() removed in favor of HAPI_ComposeObjectList() and HAPI_GetComposedObjectTransforms().
  7. (New) HAPI_GetObjectInfo() added for convenience.
  8. (New) HAPI_GetObjectTransform() added for convenience.
  9. (New) HAPI_ComposeObjectList(), HAPI_GetComposedObjectList(), and HAPI_GetComposedObjectTransforms() added to replace HAPI_GetObjects() and HAPI_GetObjectTransforms().
  10. (New) HAPI_GetInstancedObjectIds() added to get the node ids of the objects being instanced.
  11. (Modified) HAPI_GetInstanceTransforms() and HAPI_SetObjectTransform() now just take the node id of the instancer object, instead of asset id, object id, and geo id.


  1. (Removed) HAPI_GeoId typedef removed since it is now just a HAPI_NodeId.
  2. (Removed) HAPI_GeoInfo::id member since it is now just a HAPI_NodeId and that is already stored in HAPI_GeoInfo::nodeId.
  3. (New) HAPI_GetDisplayGeoInfo() added to quickly give you the display SOP node id inside an object node.
  4. (Modified) HAPI_GetGeoInfo(), HAPI_GetPartInfo(), HAPI_GetFaceCounts(), HAPI_GetVertexList(), HAPI_GetAttributeInfo(), HAPI_GetAttributeNames(), HAPI_GetAttributeIntData(), HAPI_GetAttributeInt64Data(), HAPI_GetAttributeFloatData(), HAPI_GetAttributeFloat64Data(), HAPI_GetAttributeStringData(), HAPI_GetGroupNames(), HAPI_GetGroupMembership(), HAPI_GetInstancedPartIds(), HAPI_GetInstancerPartTransforms(), HAPI_SetPartInfo(), HAPI_SetFaceCounts(), HAPI_SetVertexList(), HAPI_AddAttribute(), HAPI_SetAttributeIntData(), HAPI_SetAttributeInt64Data(), HAPI_SetAttributeFloatData(), HAPI_SetAttributeFloat64Data(), HAPI_SetAttributeStringData(), HAPI_AddGroup(), HAPI_SetGroupMembership(), HAPI_CommitGeo(), and HAPI_RevertGeo() now just take the HAPI_NodeId of the SOP node, instead of the asset, object, geo ids.
  5. (Modified) HAPI_GetAttributeIntData() now takes an extra optional stride argument.
  6. (Modified) HAPI_GetGroupMembership() now takes an extra optional membership_array_all_equal argument.
  7. (Removed) HAPI_SetGeoInfo() removed as it never did anything anyway.
  8. (Modified) HAPI_AddGroup() now takes a HAPI_PartId argument.
  9. (Modified) HAPI_StorageType enum order has changed.
  10. (New) HAPI_CookOptions::splitPointsByVertexAttributes member added to enable face and vertex reduction optimization by creating more points to make attributes unshared.
  11. (Modified) HAPI_PartInfo::pointAttributeCount, HAPI_PartInfo::pointAttributeCount, HAPI_PartInfo::pointAttributeCount, and HAPI_PartInfo::pointAttributeCount have been converted to a single member that is an array of counts, called HAPI_PartInfo::attributeCounts[].

Inter-Asset Connections

  1. (Removed) HAPI_ConnectAssetTransform, HAPI_DisconnectAssetTransform, HAPI_ConnectAssetGeometry, and HAPI_DisconnectAssetGeometry removed in favor of HAPI_GetParmNodeValue(), HAPI_SetParmNodeValue(), HAPI_ConnectNodeInput(), and HAPI_DisconnectNodeInput().
  2. (Removed) HAPI_GeoInputInfo struct removed as it is no longer used.


  1. (Removed) HAPI_MaterialId typedef removed since it is now just a HAPI_NodeId.
  2. (Removed) HAPI_MaterialInfo::id member since it is now just a HAPI_NodeId and that is already stored in HAPI_MaterialInfo::nodeId.
  3. (Removed) HAPI_GetMaterialIdsOnFaces() in favor of HAPI_GetMaterialNodeIdsOnFaces().
  4. (New) HAPI_GetMaterialNodeIdsOnFaces() added to replace HAPI_GetMaterialIdsOnFaces().
  5. (Modified) HAPI_GetMaterialInfo(), HAPI_RenderTextureToImage(), HAPI_GetImageInfo(), HAPI_SetImageInfo(), HAPI_GetImagePlaneCount(), HAPI_GetImagePlanes(), HAPI_ExtractImageToFile(), HAPI_ExtractImageToMemory(), and HAPI_GetImageMemoryBuffer() now just take the HAPI_NodeId of the material node instead of the asset id and old material id.
  6. (Removed) HAPI_GetMaterialOnPart() removed in favor of HAPI_GetMaterialNodeIdsOnFaces().
  7. (Removed) HAPI_GetMaterialOnGroup() removed in favor of HAPI_GetMaterialNodeIdsOnFaces().
  8. (New) HAPI_RenderCOPToImage() added to allow direct COP node render to an image.
  9. (New) All material APIs now also work with the new VOP-based materials.
  10. (Removed) HAPI_MaterialInfo::assetId removed as the material is no longer specific to an asset.


  1. (Modified) HAPI_ResetSimulation() now takes a HAPI_NodeId instead of a HAPI_AssetId.


  1. (Modified) HAPI_GetVolumeInfo(), HAPI_GetFirstVolumeTile(), HAPI_GetNextVolumeTile(), HAPI_GetVolumeVoxelFloatData(), HAPI_GetVolumeTileFloatData(), HAPI_GetVolumeVoxelIntData(), HAPI_GetVolumeTileIntData(), HAPI_SetVolumeInfo(), HAPI_SetVolumeTileFloatData(), and HAPI_SetVolumeTileIntData() now take just a HAPI_NodeId instead of the asset id, object id, and geo id.
  2. (New) HAPI_GetHeightFieldData() and HAPI_SetHeightFieldData() added to easily get/set height field 2D volume data as a flat array.
  3. (New) HAPI_SetVolumeVoxelFloatData(), HAPI_SetVolumeVoxelIntData() added to set individual voxel values on volumes.
  4. (New) HAPI_GetVolumeBounds() added to easily access a volume's minimum, maximum and center bound values.


  1. (Modified) HAPI_GetCurveInfo(), HAPI_GetCurveCounts(), HAPI_GetCurveOrders(), HAPI_GetCurveKnots(), HAPI_SetCurveInfo(), HAPI_SetCurveCounts(), HAPI_SetCurveOrders(), and HAPI_SetCurveKnots() now take just a HAPI_NodeId instead of the asset id, object id, and geo id.

Basic Primitives

  1. (New) HAPI_PARTTYPE_BOX and HAPI_PARTTYPE_SPHERE part type enums added for the new primitive types.
  2. (New) HAPI_CookOptions::handleBoxPartTypes and HAPI_CookOptions::handleSpherePartTypes members added to enable or disable handling of the new primitive types.
  3. (New) HAPI_GetBoxInfo() added to get information for reproducing a box primitive.
  4. (New) HAPI_GetSphereInfo() added to get information for reproducing a sphere primitive.
  5. (New) HAPI_BoxInfo struct added for box primitive support.
  6. (New) HAPI_SphereInfo struct added for sphere primitive support.


  1. (Modified) HAPI_SaveGeoToFile(), HAPI_LoadGeoFromFile(), HAPI_GetGeoSize(), HAPI_SaveGeoToMemory(), and HAPI_LoadGeoFromMemory() now take just a HAPI_NodeId instead of the asset id, object id, and geo id.

Equivalence to Old APIs

In HAPI3.0, object path parameters are no more considered as inputs and will not be counted with the SOP inputs in HAPI_NodeInfo::inputCount. Instead you should look for them in the asset's parameter list. Object path parameters will have their HAPI_ParmInfo::type set to HAPI_PARMTYPE_NODE type and should have their HAPI_ParmInfo::inputNodeType set to HAPI_NODETYPE_ANY, HAPI_NODETYPE_SOP or HAPI_NODETYPE_OBJ. Since these nodes are already object_merges, it is no longer necessary to connect them using HAPI_ConnectNodeInput(). You should instead connect them using HAPI_SetParmNodeValue() with the node id of the input node you created. See Inter-Asset Connections for more info.


bool auto_close = true;
int port = 5;
float timout_ms = 1000;
HAPI_ProcessId process_id = 0;
HAPI_StartThriftSocketServer( auto_close, port, timeout_ms, &process_id );
HAPI_StartThriftNamedPipeServer( auto_close, port, timeout_ms, &process_id );
HAPI_ThriftServerOptions thrift_server_options = HAPI_ThriftServerOptions_Create();
HAPI_StartThriftSocketServer( &thrift_server_options, port, &process_id );
HAPI_StartThriftNamedPipeServer( &thrift_server_options, port, &process_id );


// Common Variables.
HAPI_Bool use_cooking_thread = true;
int cooking_thread_stack_size = -1;
const char * houdini_environment_files = "~/file1.env:~/file2.env";
const char * otl_search_path = nullptr;
const char * dso_search_path = nullptr;
const char * image_dso_search_path = nullptr;
const char * audio_dso_search_path = nullptr;
HAPI_SetEnvFiles( &session, houdini_environment_files );
&session, &cook_options, use_cooking_thread,
// HAPI_SetEnvFiles() has been removed!
&session, &cook_options, use_cooking_thread,


Checking validity:

int answer = 0;
int asset_validation_id = 0; // From the ::HAPI_AssetInfo struct.
HAPI_IsAssetValid( &session, asset_id, asset_validation_id, &answer );
int answer = 0;
int unique_node_id = 0; // From the ::HAPI_NodeInfo struct.
HAPI_IsNodeValid( &session, node_id, unique_node_id, &answer );


// Returned by HAPI_GetAvailableAssets().
const char operator_name = "SOP/HAPI_Test_Assets_SOP";
HAPI_InstantiateAsset( nullptr, operator_name, true, &asset_id );
HAPI_CreateNode( nullptr, -1, operator_name, nullptr, true, &node_id );

Creating a curve:

HAPI_CreateCurve( nullptr, &asset_id );
HAPI_CreateNode( nullptr, -1, "SOP/curve", nullptr, true, &node_id );

Creating the input asset:

HAPI_CreateInputAsset( nullptr, &asset_id, "input_asset" );
HAPI_CreateInputNode( nullptr, &node_id, "input_asset" );

Destroying an asset:

HAPI_DestroyAsset( nullptr, asset_id );
HAPI_DeleteNode( nullptr, node_id );

Cooking an asset:

HAPI_AssetId asset_id = 0; // Returned by HAPI_InstantiateAsset().
HAPI_CookAsset( nullptr, asset_id, nullptr );
HAPI_NodeId node_id = 0; // Returned by HAPI_CreateNode().
HAPI_CookNode( nullptr, node_id, nullptr );

Getting and setting asset tranform:

HAPI_GetAssetTransform( nullptr, asset_id, rst_order, rot_order, &transform_euler );
HAPI_SetAssetTransform( nullptr, asset_id, &transform_euler );
HAPI_GetObjectTransform( nullptr, node_id, -1, rst_order, &transform );
HAPI_SetObjectTransform( nullptr, node_id, &transform );

Getting asset input name:

// Common Variables
int node_input_idx = 0;
int parameter_input_idx = 1; // An input that is actually an exposed node path parameter.
HAPI_NodeType input_type;
HAPI_GetInputName( nullptr, asset_id, node_input_idx, (int) input_type, &name );
HAPI_GetInputName( nullptr, asset_id, parameter_input_idx, (int) input_type, &name );
HAPI_ParmId parm_id = 0; // Need the parm id of the parameter corresponding to parameter_input_idx.
HAPI_ParmInfo parm_info = HAPI_ParmNode_Create();
HAPI_GetNodeInputName( nullptr, node_id, node_input_idx, &name ) );
HAPI_GetParmInfo( nullptr, node_id, parm_id, &parm_info );
name = parm_info.nameSH;

HIP Files

int new_asset_count = 0;
HAPI_CheckForNewAssets( nullptr, &new_asset_count );
std::vector< HAPI_AssetId > asset_ids_array( new_asset_count );
HAPI_GetNewAssetIds( nullptr, asset_ids_array.data(), new_asset_count );
int child_node_count = 0;
const bool recursive = false;
HAPI_NodeId obj_manager; HAPI_GetManagerNodeId( nullptr, HAPI_NODETYPE_OBJ, &obj_manager );
nullptr, obj_manager, HAPI_NODETYPE_OBJ, HAPI_NODEFLAGS_DISPLAY, recursive, &child_node_count );
std::vector< HAPI_NodeId > child_nodes( child_node_count );
nullptr, obj_manager, child_nodes.data(), child_node_count );
// Then just go through all the returned node ids and see which ones you know about and which you don't.


Getting all editable networks in an asset:

HAPI_AssetId asset_id = <Returned by HAPI_InstantiateAsset()>;
HAPI_AssetInfo asset_info;
HAPI_NodeId editable_network_node_id; // Not an array for simplicity.
HAPI_GetAssetInfo( nullptr, asset_id, &asset_info ) );
nullptr, asset_id, &editable_network_node_id, 1 ) );
HAPI_NodeId node_id = <Returned by HAPI_CreateNode()>;
int editable_network_count = 0;
const bool recursive = true;
nullptr, node_id,
&editable_network_count );
std::vector< HAPI_NodeId > editable_networks( editable_network_count );
nullptr, node_id, editable_networks.data(), editable_network_count );


Get all object infos and their transforms in an asset.

HAPI_AssetInfo asset_info = <from HAPI_GetAssetInfo()>;
std::vector< HAPI_ObjectInfo > object_infos( asset_info.objectCount );
nullptr, asset_info.id, object_infos.data(), 0, asset_info.objectCount );
std::vector< HAPI_Transform > object_transforms( asset_info.objectCount );
nullptr, asset_info.id, rst_order, object_transforms.data(), 0, asset_info.objectCount );
int object_count = 0;
HAPI_ComposeObjectList( nullptr, asset_node_id, nullptr, &object_count );
std::vector< HAPI_ObjectInfo > object_infos( object_count );
nullptr, asset_node_id, object_infos.data(), 0, object_count );
std::vector< HAPI_Transform > object_transforms( object_count );
nullptr, asset_node_id, rst_order, object_transforms.data(), 0, object_count );

Get object instance transforms from an instancer object.

std::vector< HAPI_Transform > instance_transforms( geo_point_count );
nullptr, asset_id, object_id, geo_id, rst_order,
instance_transforms.data(), 0, geo_point_count );
std::vector< HAPI_Transform > instance_transforms( geo_point_count );
nullptr, object_node_id, rst_order,
instance_transforms.data(), 0, geo_point_count );


Get and set geometry information (assuming asset has a single object).

HAPI_AssetId asset_id;
HAPI_InstantiateAsset( nullptr, ..., &asset_id );
HAPI_ObjectId object_id = 0;
HAPI_GeoId geo_id = 0;
HAPI_GeoInfo geo_info;
HAPI_GetGeoInfo( nullptr, asset_id, object_id, geo_id, &geo_info );
// All other geometry getters and settings will take the asset_id, object_id, geo_id as identifiers.
HAPI_NodeId asset_node_id;
HAPI_CreateNode( nullptr, ..., &node_id );
int object_count = 0;
nullptr, asset_node_id, HAPI_NODETYPE_OBJ, HAPI_NODEFLAGS_OBJ_GEOMETRY, &object_count );
HAPI_NodeId object_node_id;
nullptr, asset_node_id, &object_node_id, 0, object_count );
HAPI_GeoInfo geo_info;
HAPI_GetDisplayGeoInfo( nullptr, object_node_id, &geo_info );
// All other geometry getters and setters take just the geo_info.nodeId.

Inter-Asset Connections

// Common Variables
int node_input_idx = 0;
int parameter_input_idx = 1; // Input that is actually an exposed parameter.
HAPI_AssetId asset_a = 1;
HAPI_ObjectId asset_a_obj = 0;
HAPI_AssetId asset_b = 2;
// For a node input.
HAPI_ConnectAssetTransform( nullptr, asset_a, asset_b, node_input_idx )
HAPI_DisconnectAssetTransform( nullptr, asset_b, node_input_idx );
HAPI_ConnectAssetGeometry( nullptr, asset_a, asset_a_obj, asset_b, node_input_idx );
HAPI_DisconnectAssetGeometry( nullptr, asset_b, node_input_idx );
// For a parameter input.
HAPI_ConnectAssetTransform( nullptr, asset_a, asset_b, parameter_input_idx )
HAPI_DisconnectAssetTransform( nullptr, asset_b, parameter_input_idx );
HAPI_ConnectAssetGeometry( nullptr, asset_a, asset_a_obj, asset_b, parameter_input_idx );
HAPI_DisconnectAssetGeometry( nullptr, asset_b, parameter_input_idx );
HAPI_NodeId node_a = 1;
HAPI_NodeId node_a_obj = 3;
HAPI_NodeId node_b = 2;
// For a node input
HAPI_ConnectNodeInput( nullptr, node_b, node_input_idx, node_a );
HAPI_DisconnectNodeInput( nullptr, node_b, node_input_idx );
HAPI_ConnectNodeInput( nullptr, node_b, node_input_idx, node_a_obj );
HAPI_DisconnectNodeInput( nullptr, node_b, node_input_idx );
// For a parameter input.
// You need to find the equivalent parm name of what used to be parameter_input_idx.
const char * input_parm_name = "coord";
HAPI_SetParmNodeValue( nullptr, node_b, input_parm_name, node_a );
HAPI_SetParmNodeValue( nullptr, node_b, input_parm_name, node_a_obj );
HAPI_SetParmNodeValue( nullptr, node_b, input_parm_name, -1 );


Getting material assignments and material infos.

HAPI_PartInfo part_info = <the part info of the part with the material>;
std::vector< HAPI_MaterialId > materials( part_info.faceCount );
nullptr, asset_id, object_id, geo_id, part_info.id,
&are_all_the_same, materials.data(), 0, part_info.faceCount );
HAPI_MaterialInfo material_info;
HAPI_GetMaterialInfo( nullptr, asset_id, materials[ 0 ], &material_info );
// All other material getters and setters take the asset id and material id as identifiers.
HAPI_PartInfo part_info = <the part info of the part with the material>;
std::vector< HAPI_NodeId > materials( part_info.faceCount );
nullptr, sop_node_id, part_info.nodeId, &are_all_the_same,
materials.data(), 0, part_info.faceCount );
HAPI_MaterialInfo material_info;
HAPI_GetMaterialInfo( nullptr, materials[ 0 ], &material_info );
// All other materials getters and setters take just the material node id as the sole identifier.